3

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

这是我得到的一个结果:

业务实体 ID、SaliedFlag

7,1

5,1

3,1

1,1

2,0

4,0

6,0

8,0

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

4

4 回答 4

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 或 null 时,第一个排序字段是 BusinessEntityID。
这会将 SalariedFlag = 0 的所有行组合在一起,因为它们都有一个空的第一个排序字段。
SalariedFlag = 1 的行将按 BusinessEntityID 排序。看起来空值按降序排列在最后,所以所有 SalariedFlag != 1 排在最后。

这是主要排序,对于次要排序,发生的情况大致相同:
SalriedFlag = 0 的所有行都将按 BusinessEntityID 排序。由于它们的主要排序字段全部为空,它们最终将按 BusinessEntityID 排序。

并且 SalariedFlag != 0 的所有行将与 null 二级排序组合在一起。如果这些行的 SalariedFlag = 1,那么它们已经按主排序进行了排序。

如果 SalariedFlag 只能是 0 或 1,那么这种排序可以(稍微)简化为:

ORDER BY CASE SalariedFlag WHEN 1 THEN BusinessEntityID END DESC
        , BusinessEntityID;
于 2012-05-18T00:29:57.430 回答
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,那将是完全不同的事情,并且该查询将不再起作用,那些具有相同的flag 不一定彼此相邻。

NULL 先排序,如果指定DESC,则最后排序。

现场测试:http ://www.sqlfiddle.com/#!3/1b849/13


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

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

于 2012-05-18T01:26:41.677 回答
1

您首先BusinessEntityID在标志时订购1,然后BusinessEntityID在标志时解决关系0。这是因为第一个CASE表达式的计算结果为nullwhen SalariedFlagis not 1,因此所有带有 标志的记录0都被移到带有 标志的记录之后1

于 2012-05-18T00:29:38.220 回答
0

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

于 2012-05-18T00:21:28.273 回答