如何在并列选择中保持列值的顺序?

时间:2018-07-03 13:21:33

标签: sql-server tsql

我正在使用SELECTUNION批量插入表中。调用SELECT时,我需要INSERT值的顺序保持不变,但似乎这些值是以升序而不是我指定的顺序插入的。

例如,下面的插入语句

declare @QuestionOptionMapping table
(
    [ID] [int] IDENTITY(1,1)
  , [QuestionOptionID] int
  , [RateCode] varchar(50)
)

insert into @QuestionOptionMapping (
    RateCode
)
select
   'PD0116'
union
select
  'PL0090'
union
select
  'PL0091'
union
select
  'DD0026'
union
select
  'DD0025'

SELECT * FROM @QuestionOptionMapping

将数据呈现为

(5 row(s) affected)
ID          QuestionOptionID RateCode
----------- ---------------- --------------------------------------------------
1           NULL             DD0025
2           NULL             DD0026
3           NULL             PD0116
4           NULL             PL0090
5           NULL             PL0091

(5 row(s) affected)

所选择的插入数据如何返回与插入时相同的顺序?

4 个答案:

答案 0 :(得分:5)

SQL Server将您的行存储为无序集。数据点可以是连续的,也可以不是连续的,并且它们可以按照在插入语句中指定的数据的“顺序”,也可以不是。

查询数据时,引擎将按优化程序确定的最有效顺序检索行。不能保证每次查询数据时顺序都相同。

保证结果集顺序的唯一方法是在SELECT语句中包含一个显式的ORDER BY子句。

请参阅此答案,以更深入地讨论为何如此。 Default row order in SELECT query - SQL Server 2008 vs SQL 2012

通过对INSERT语句使用SELECT / UNION选项,可以创建SQL Server作为一组而不是一系列输入提取的无序集合。如果需要按顺序应用IDENTITY值,则将插入语句分成离散语句。更好的是,如果行编号很重要,请不要碰碰运气。明确编号插入行。

答案 1 :(得分:3)

SQL表确实表示无序集。但是,identity上的insert列将遵循order by的顺序。

由于union中的重复消除,您的数据混乱了。但是,我建议编写查询以对数据进行显式排序:

insert into @QuestionOptionMapping (RateCode)
    select ratecode
    from (values (1, 'PD0116'), 
                 (2, 'PL0090'),
                 (3, 'PL0091'),
                 (4, 'DD0026'),
                 (5, 'DD0025')
         ) v(ord, ratecode)
    order by ord;

然后请确保使用order by进行选择:

select qom.*
from @QuestionOptionMapping qom
order by id;

请注意,这还使用了values()表构造函数,这是一种非常方便的语法。

答案 2 :(得分:0)

如果您不从表格中进行选择?
然后,您可以插入VALUES,而不是带有并集的选择。

insert into @QuestionOptionMapping (RateCode) values
 ('PD0116')
,('PL0090')
,('PL0091')
,('DD0026')
,('DD0025')

或者在您的查询中,将所有UNION更改为UNION ALL。

UNION和UNION ALL之间的区别在于UNION将删除重复的行。 而UNION ALL只是从选择中抽出结果集。
为了使UNION能够找到这些重复项,首先必须在内部对其进行排序。
但是UNION ALL并不关心唯一性,因此不需要排序。

第三个选择是将一个插入语句更改为多个插入语句。 每个值一个插入。从而完全避免使用UNION。
但是,这种反高尔夫编码方法也最罗word。

答案 3 :(得分:0)

您的问题是您没有按照您的认为的顺序排列它们。 UNION仅是不同的值,通常会对这些值进行排序以促进不同。单独运行select语句,您将看到。

如果您使用values进行插入,则会保留订单:

insert into @QuestionOptionMapping (RateCode) values
('PD0116'), ('PL0090'), ('PL0091'), ('DD0026'), ('DD0025')

select * from @QuestionOptionMapping order by ID