2012-05-18 3 views
3

http://msdn.microsoft.com/en-us/library/ms181765.aspxSQL: саз в порядке п

Я вижу 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

Может ли кто-нибудь объяснить, почему записи с той же салой riedFlag находятся рядом друг с другом, и почему salariedFlag = 1 кусок находится над куском salariedFlag = 0?

ответ

5

Оговорка сортировки эквивалентно следующему, который может быть немного более очевидным:

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

Итак, первое поле сортировки является BusinessEntityID при SalariedFlag = 1, или нуль.
Это будет группировать все строки, где 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; 
+0

Отличный ответ, спасибо! –

0

Попробуйте включить операторы case в список значений, которые вы выбираете обратно. Это должно помочь прояснить, на какие значения действительно происходит сортировка.

+0

: SalariedFlag уже в списке выбора –

+0

SalariedFlag - это не то, о чем я говорю. Попробуйте включить CASE SalariedFlag WHEN 1 THEN BusinessEntityID END , CASE WHEN SalariedFlag = 0 THEN BusinessEntityID END – GaTechThomas

1

Вы заказываете сначала BusinessEntityID, когда флаг 1, а затем решить связи по BusinessEntityID, когда флаг 0. Это связано с тем, что первое выражение CASE оценивается как null, когда SalariedFlag не 1, поэтому все записи с флагом 0 переносятся после записей с флагом 1.

2

Вы можете легко визуализировать, почему он сортируется таким образом, включив в случае, когда условия на ЗЕЬЕСТ:

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 пребывание вместе, все они падают (посмотрите на столбец A) под нулевым значением, это было бы совсем другое дело, если есть другое значение для SalariedFlag, скажем, номер 2, и этот запрос больше не будет работать, те, у кого одинаковый флаг, необязательно могут быть следующими друг друга.

NULL сортировать в первую очередь, если вы укажете DESC, он отсортируется последним.

Живая тест: http://www.sqlfiddle.com/#!3/1b849/13


Признавая СЛУЧАЙ этого запроса в КОГДА это ТОГДА использует 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

Смежные вопросы