与联盟的行为有奇怪的顺序

时间:2014-09-23 16:40:41

标签: sql sql-server tsql

有人可以向我解释这里发生了什么。这种行为并不像我期望的那样:

select category,timefield from test where category='A'
union
select top 10 category,timefield from test where category='B' order by timefield desc

我想要的是A类的所有行,只有B类中最近的10行 执行时,结果实际上是:所有类别A(按时间字段降序排序)+ 第一个 10行B类(按时间字段降序排序)

更奇怪的是,如果我们把这整个语句放在一个子查询中,我希望这个行为保持不变并像以前那样进行评估,但事实并非如此:

select * from (
    select category,timefield from test where category='A'
    union
    select top 10 category,timefield from test where category='B' order by timefield desc
) subq

这将返回所有类别A(按升序排列)+最近的10类B类(按降序排列)。 这正是我想要的。

为什么第一个陈述没有产生我所期望的,为什么第二个陈述的表现非常不同?

(这是SQL Server 2008)

1 个答案:

答案 0 :(得分:5)

您需要在第一个查询中使用括号,因为order by会应用于union的结果。它被解释为:

(select category,timefield from test where category='A'
 union
 select top 10 category,timefield from test where category='B'
)
order by timefield desc

(我不是说这是有效的语法。)

而你想要的是:

(select category, timefield from test where category='A')
union
(select top 10 category, timefield from test where category='B' order by timefield desc)

请注意union将删除重复项。如果您不想要这笔额外费用,请改用union all

至于为什么这是一个子查询,我的猜测是巧合。当您在没有top的情况下使用order by时,SQL Server无法保证返回结果 - 甚至从一次调用到下一次调用时结果都是一致的。有时它实际上可能会做你想要的。