SQL:case语句按顺序by子句

时间:2012-05-18 00:11:12

标签: sql sql-server sql-order-by case

http://msdn.microsoft.com/en-us/library/ms181765.aspx

我从上面的链接看到下面的sql:

SELECT BusinessEntityID, SalariedFlag
FROM HumanResources.Employee
ORDER BY CASE SalariedFlag WHEN 1 THEN BusinessEntityID END DESC
    ,CASE WHEN SalariedFlag = 0 THEN BusinessEntityID END;
GO

以下是我得到的一个结果:

  

BusinessEntityID,SalariedFlag

     

7,1

     

5,1

     

3,1

     

1,1

     

2,0

     

4,0

     

6,0

     

8,0

有人可以解释为什么具有相同salariedFlag的记录彼此相邻以及为什么salariedFlag = 1 chunk高于salariedFlag = 0块?

4 个答案:

答案 0 :(得分:5)

sort子句等同于以下内容,可能稍微明显一点:

ORDER BY CASE SalariedFlag WHEN 1 THEN BusinessEntityID ELSE null END DESC
        ,CASE WHEN SalariedFlag = 0 THEN BusinessEntityID ELSE null END;

因此,当SalariedFlag = 1时,第一个排序字段是BusinessEntityID,或者为null 这会将SalariedFlag = 0的所有行组合在一起,因为它们都有一个空的第一个排序字段 SalariedFlag = 1的行将按BusinessEntityID排序。看起来nulls以降序排序最后排序,所以所有SalariedFlag!= 1都是最后一个。

这是主要类型,对于次要排序,发生了同样的事情:
SalariedFlag = 0的所有行都将按BusinessEntityID排序。由于它们的主要排序字段都为空,因此最终将按BusinessEntityID排序。

SalariedFlag!= 0的所有行将与空的二级排序组合在一起。如果这些行的SalariedFlag = 1,则它们已经按主要顺序排序。

如果SalariedFlag只能是0或1,那么这种情况可以(略微)简化为:

ORDER BY CASE SalariedFlag WHEN 1 THEN BusinessEntityID END DESC
        , BusinessEntityID;

答案 1 :(得分:2)

通过在SELECT子句中包含CASE WHEN条件,可以很容易地想象它为什么按照这种方式排序:

SELECT BusinessEntityID, SalariedFlag,

CASE SalariedFlag WHEN 1 THEN BusinessEntityID END AS A,
CASE WHEN SalariedFlag = 0 THEN BusinessEntityID END AS B

FROM Employee
ORDER BY CASE SalariedFlag WHEN 1 THEN BusinessEntityID END DESC
    ,CASE WHEN SalariedFlag = 0 THEN BusinessEntityID END;

输出:

BUSINESSENTITYID  SALARIEDFLAG      A                 B
7                 1                 7                 (null)
5                 1                 5                 (null)
3                 1                 3                 (null)
1                 1                 1                 (null)
2                 0                 (null)            2
4                 0                 (null)            4
6                 0                 (null)            6
8                 0                 (null)            8

SalariedFlag 0保持在一起的原因是,它们都在null下看到(看A列),如果SalariedFlag有另一个值,比如说2号,则完全是另一回事,并且该查询将不再起作用,那些拥有相同旗帜的人不一定会彼此相邻。

NULL排序首先,如果指定DESC,它将排序最后。

实时测试:http://www.sqlfiddle.com/#!3/1b849/13


认识到查询的CASE WHEN的THEN使用的是整数类型的BusinessEntityID,您可以执行以下查询来实现相同的效果;并且因为它使用SalariedFlag作为分隔符,所以以下查询 可能 更快,因为您没有在ORDER BY上使用条件。您只需切换SalariedFlag并对其进行排序:

-- just to visualize things up
SELECT BusinessEntityID, SalariedFlag,

    A = BusinessEntityID * SalariedFlag,
    B = BusinessEntityID * (SalariedFlag ^ 1) 

FROM Employee
ORDER BY A DESC, B 

-- in actual you do this:

SELECT BusinessEntityID, SalariedFlag

FROM Employee
ORDER BY BusinessEntityID * SalariedFlag DESC, BusinessEntityID * (SalariedFlag ^ 1) 

鉴于此数据:

CREATE TABLE [Employee]
    ([BusinessEntityID] int, [SalariedFlag] int);

INSERT INTO [Employee]
    ([BusinessEntityID], [SalariedFlag])
VALUES
    (10, 1),
    (5, 1),
    (9, 1),
    (1, 1),
    (2, 0),
    (7, 0),
    (6, 0),
    (8, 0);

这是输出:

BUSINESSENTITYID  SALARIEDFLAG      A                 B
10                1                 10                0
9                 1                 9                 0
5                 1                 5                 0
1                 1                 1                 0
2                 0                 0                 2
6                 0                 0                 6
7                 0                 0                 7
8                 0                 0                 8

实时测试:http://www.sqlfiddle.com/#!3/e65ac/2

答案 2 :(得分:1)

当标记为BusinessEntityID时,您首先按1排序,然后在标记为BusinessEntityID时按0解析关联。这是因为当CASE不是null时,第一个SalariedFlag表达式的计算结果为1,因此标记为0的所有记录都将移至记录之后标志为1

答案 3 :(得分:0)

尝试在您选择的值列表中包含case语句。它应该有助于澄清排序实际发生的值。