Случай использования после заказа - PullRequest
1 голос
/ 17 апреля 2019

Я читал книгу SQL, один из вопросов:

Напишите запрос к таблице Sales.Customers, которая возвращает для каждого клиента идентификатор клиента и регион.Сортировка строк в выходных данных по регионам с сортировкой меток NULL в последнюю очередь (после значений, отличных от NULL). Обратите внимание, что поведение сортировки по умолчанию для меток NULL в T-SQL заключается в сортировке первой (перед значениями, отличными от NULL).

enter image description here

И ответ таков:

SELECT custid, region
FROM Sales.Customers
ORDER BY
 CASE WHEN region IS NULL THEN 1 ELSE 0 END, region;

Я могу понять идею, но все еще в замешательстве, давайте возьмем записьс custid = 9 , например: поскольку custid 9 имеет нулевую область, в случае cstatement возвращает 1, поэтому запрос выглядит так:

ORDER BY 1, region

, что эквивалентно:

ORDER BY custid, region  --because custid is the first column

так почему же Custid 9 не предшествует Custid 10 (вторая запись в выводе)?разве этот вывод не нужно сначала упорядочить по custid, поэтому 9 - до 10?

Ответы [ 5 ]

2 голосов
/ 17 апреля 2019

Ваша интерпретация неверна. 1 - это просто число, а не ссылка на столбец.

Запрос эквивалентен:

SELECT custid, region
FROM (SELECT c.*,
             (CASE WHEN region IS NULL THEN 1 ELSE 0 END) as region_is_null
      FROM Sales.Customers c
     ) c
ORDER BY region_is_null, region;

Это важное различие о числах в ORDER BY. Выражение:

ORDER BY 1

относится к первому столбцу. Тем не менее,

ORDER BY 1 + 0

- это просто числовое выражение, которое возвращает константу 1 - и приведет к ошибке в SQL Server (что не позволяет использовать константы в ORDER BY).

1 голос
/ 17 апреля 2019
ORDER BY CASE
           WHEN region IS NULL THEN
             1
           ELSE
             0
         END,
         region

не эквивалентно

ORDER BY 1,
         region

, поскольку во втором столбец сортировки по первому столбцу всегда постоянен, а в первом он может меняться в зависимости от CASE.

И

ORDER BY 1,
         region

также не эквивалентно

ORDER BY custid,
         region

, снова в первом 1 является постоянным, но custid является переменным.

1018 *

ORDER BY CASE
           WHEN region IS NULL THEN
             1
           ELSE
             0
         END,
         region

«генерирует» новый столбец для сортировки в зависимости от содержимого region.Этот новый столбец получает 1, если region равно нулю 0 в противном случае.Если вы представите этот новый столбец в таблице, он будет выглядеть так:

custid | region | new column
...
10     | BC     | 0
...
9      | NULL   | 1
...

Теперь, если это будет отсортировано по новому столбцу и региону, клиент с идентификатором 10 окажется перед клиентом с идентификатором 9.потому что тот с идентификатором 10 имеет меньшее значение для нового столбца - 0 против 1 от клиента с идентификатором 9.

1 голос
/ 17 апреля 2019

поэтому запрос выглядит как

ORDER BY 1, region

Нет, это неправильно. Выражение CASE WHEN region IS NULL THEN 1 ELSE 0 END вычисляется для каждой строки; и 1 является значением вместо позиции столбца. Положение столбца внутри ORDER BY может указываться только как литерал, а не как выражение. Итак, это:

custid    region
8         NULL
9         NULL
10        BC
42        BC
45        CA

становится:

custid    region    case...
8         NULL      1
9         NULL      1
10        BC        0
42        BC        0
45        CA        0

И отсортированные результаты могут быть:

custid    region    case...
10        BC        0
42        BC        0
45        CA        0
8         NULL      1
9         NULL      1

Или:

custid region case...
42     BC     0
10     BC     0
45     CA     0
9      NULL   1
8      NULL   1
0 голосов
/ 17 апреля 2019

Идея состоит в том, чтобы использовать оператор CASE, чтобы создать виртуальный столбец для вычисления нулей как 0 и нулевых нулей как 1, а затем отсортировать соответственно.

если вы используете 0 в предложении order by, вы получите ошибку, потому что у вас нет столбца в позиции 0, также, если вы измените порядок выбранных столбцов, результат будет таким же. поэтому вывод оператора case - это не позиция столбца, а вычисляемый столбец.

customer_id        region      marker
not important      if null        0
0 голосов
/ 17 апреля 2019

Вы можете попробовать ниже - в вашем случае 0 будет сначала comign, а затем 1, поэтому вам нужно изменить порядок значений, или вы можете сделать desc order, если вы не хотите изменять значение

SELECT custid, region
FROM Sales.Customers
ORDER BY
 CASE WHEN region IS NULL THEN 0 ELSE 1 END, region
...