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

时间:2010-05-20 01:38:59

标签: sql-server-2008 join

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

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

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

我正在寻找一种有效的方法来确保连接中结果的顺序与id插入临时表时的顺序相匹配,这样返回的用户列表的顺序与输入的人员名单。

我考虑了以下替代方案:

  1. 使用“#p inner join users”,以防保留左表的顺序
  2. 使用“#p left join users where id is null”,以防左连接保留顺序且内连接不
  3. 使用“create table(rownum int,personid bigint)”,插入一个递增的行号作为临时表,因此结果可以通过rownum在连接中排序
  4. 使用与DB2中提供的“按顺序排序[tablename]”子句相同的SQL Server
  5. 我目前正在使用选项3,它有效...但我讨厌使用order by子句来处理已经订购的东西。我只是不知道临时表是否保留了插入行的顺序或连接的操作方式以及结果的输出顺序。

    编辑:

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

1 个答案:

答案 0 :(得分:3)

除非您使用order by子句明确地对它们进行排序,否则永远不会对SQL集进行排序。

这样做:

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>;

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

你写道:

  

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

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

select * form users where users.id in (1, 2, 3, 6, 9, ... );

你可能过早地“优化”了一些不需要优化的东西。 RDBMS(通常)被编写为高效的,并且可能会对已经按偶然排序的东西进行一些额外的工作排序。在您需要优化之前,请专注于功能。 (我说这是一个过去几个月几乎只在非常大的(大约5亿行OLTP)数据集上优化SQL的人,因为大部分时间都是如此。)