联盟不保留秩序(不稳定)

时间:2016-11-23 23:04:32

标签: sql-server tsql sql-server-2016

我执行下面的查询并期望第一组然后第二组明显但顺序是完全随机的。 我期待的结果:john,mark,dave,robert,kirk

select *
from (
    select Name
    from (values ('john'),('mark'),('dave')) X(Name)
    union
    select Name
    from (values ('robert'),('mark'),('kirk')) X(Name)
) q

这是另一种我希望订购(稳定)结果但我得到相同结果的查询。 Union All按照我的预期添加第二组,但应用Distinct稍后的中断顺序。

select Distinct Name
from (
    select Name
    from (values ('john'),('mark'),('dave')) X(Name)
    union all
    select Name
    from (values ('robert'),('mark'),('kirk')) X(Name)
) q

什么是有序和不同集合的解决方案?

5 个答案:

答案 0 :(得分:1)

WITH q AS
(
    -- Original data
    SELECT Name FROM (VALUES ('john'),('mark'),('dave')) X(Name)
    UNION ALL
    SELECT Name FROM (VALUES ('robert'),('mark'),('kirk')) X(Name)
), r AS
(
    -- Add the sequence column for ordering
    -- ** It just use natual order **
    SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS Seq, * from q
), s AS
( 
    -- Use RN to filter out the duplicates
    SELECT *, ROW_NUMBER() OVER (PARTITION BY Name ORDER BY Seq) AS RN FROM r
)
SELECT Name FROM s WHERE RN = 1 ORDER BY Seq

答案 1 :(得分:0)

如果你想要第一个设置,那么第二个设置中的每个元素之后都不在第一个设置中,那么你必须指定它。如果你想保证在第二组之前列出第一组中的东西,你还需要添加一个ORDER BY。

select q.name
from (
    select Name,n
    from 
    (values ('john'),('mark'),('dave')) X(Name)
    cross join (values (1)) y(n)

    union all

    select Name,n
    from
    (
    select Name
    from (values ('robert'),('mark'),('kirk')) X(Name)

    except

    select Name 
    from
    (values ('john'),('mark'),('dave')) X(Name)

    ) Z(Name)
    Cross join (values (2)) y(n)

) q
order by q.n

答案 2 :(得分:0)

如果我们使用值来选择数据,则不需要使用order by子句,并且我们不必担心来自该特定查询的潜在索引更改,因此您将始终拥有订单,而且我们是使用union all它只是连接结果集没有排序。

但是,如果您正在使用表,是的,订单肯定会更改取决于几个因素,例如表索引,返回的列,引入的新数据等。所以如果您希望以特定方式排序结果,你需要指定ORDER BY子句。

对于您的示例,您不需要使用下面的order by子句

select  Name
from (
    select Name
    from (values ('john'),('mark'),('dave')) X(Name)
    union all

   ( select Name
    from (values ('robert'),('mark'),('kirk')) X(Name)
    except
    select Name
    from (values ('john'),('mark'),('dave')) X(Name))

) q

答案 3 :(得分:-1)

您是否合理地将SortOrder列添加到内部SELECT语句中然后按顺序排序?类似的东西:

select Distinct Name
from (
    select SortOrder, Name
    from (values (1, 'john'),(2, 'mark'),(3, 'dave')) X(SortOrder, Name)
    union all
    select SortOrder, Name
    from (values (4, 'robert'),(2, 'mark'),(5, 'kirk')) X(SortOrder, Name)
) q
order by SortOrder ASC

答案 4 :(得分:-1)

保证订单的唯一方法是使用ORDER BY子句,这在BOL中有记载:

https://msdn.microsoft.com/en-us/library/ms188385.aspx

  

按指定的列列表对查询的结果集进行排序,并可选择将返回的行限制为指定的范围。除非指定了ORDER BY子句,否则无法保证在结果集中返回行的顺序。

如果您希望根据UNION中的顺序返回行,那么您可以执行以下操作:

select Name
from (
    select 1 as sort1, Name
    from (values ('john'),('mark'),('dave')) X(Name)
    union
    select 2 as sort1, Name
    from (values ('robert'),('mark'),('kirk')) X(Name)
) q
order by sort1, Name