内部与另一个表连接时如何保留临时表行的顺序?

Tri*_*nko 5 join sql-server-2008

SQL Server"join"是否一致地保留任何类型的行顺序(即左表或右表的行)?

伪代码:

create table #p (personid bigint);
foreach (id in personid_list)
    insert into #p (personid) values (id)
select id from users inner join #p on users.personid = #p.id
Run Code Online (Sandbox Code Playgroud)

假设我有一个与人员条目相对应的ID列表.这些ID中的每一个可以对应于零个或多个用户帐户(因为每个人可以具有多个帐户).

要从users表中快速选择列,我使用person ids填充临时表,然后将其与users表内连接.

我正在寻找一种有效的方法来确保连接中结果的顺序与id插入临时表时的顺序相匹配,这样返回的用户列表与人员列表的顺序相同因为它进入了.

我考虑过以下替代方案:

  1. 使用"#p inner join users",以防保留左表的顺序
  2. 使用"#p left join users where id is not null",以防左连接保留顺序而内连接不保留
  3. 使用"create table(rownum int,personid bigint)",插入一个递增的行号作为临时表,因此结果可以通过rownum在连接中排序
  4. 使用与DB2中提供的"按顺序排序[tablename]"子句相同的SQL Server

我目前正在使用选项3,它可以工作......但我讨厌使用order by子句来处理已经订购的东西.我只是不知道临时表是否保留了插入行的顺序或连接的操作方式以及结果的输出顺序.

编辑:

假设我使用选项3,那么有一个要订购的字段...是否有任何形式的连接将帮助SQL Server在维护订单方面做最少量的工作.我的意思是,它是否足够智能,例如,查看order by子句中的哪些表的字段,并在进行连接时首先处理该表,以便结果集的顺序大致或完全与该表的顺序一致,只是万一它已经按照预期的顺序?

tpd*_*pdi 3

SQL 集永远不会排序,除非您使用子句显式对它们进行排序order by

做这个:

create table #p (personid bigint);

insert into #p (personid) values (id)
select id from users 
ORDER BY <something like users.name>;

select * from #p 
ORDER BY <something like users.name>;
Run Code Online (Sandbox Code Playgroud)

请注意,虽然您可以按顺序插入,但这并不意味着后续的选择将被排序,因为SQL 集永远不会排序,除非您使用子句显式对它们进行排序order by

你写:

为了快速从用户表中选择列,我用人员 ID 填充临时表,然后将其与用户表进行内连接。

请注意,在大多数情况users下,使用 in 列表直接从中选择会更快:

select * form users where users.id in (1, 2, 3, 6, 9, ... );
Run Code Online (Sandbox Code Playgroud)

您可能过早地“优化”了一些不需要优化的东西。RDBMS(通常)被编写为高效的,并且可能不会对已经偶然排序的东西进行排序。专注于功能,直到您明确需要优化为止。(我这样说是因为过去几个月几乎只在非常大(大约 5 亿行 OLTP)数据集上优化 SQL 的人,因为大多数时候,这是事实。)