Порядок SQL по DECODE и CASE возвращает разные данные для одинаковых условий - PullRequest
2 голосов
/ 24 октября 2019

У меня есть запрос на выборку в ORACLE с order by, и я пытался использовать DECODE и CASE с одинаковыми условиями, но упорядочение выполняется по-разному, и я не могу понять, почему. Я думал, что проблема в NULL (null = null неизвестен), но порядок по CASE дает ожидаемый результат.

Это порядок с помощью DECODE:

order  by decode(seq_diff, abs(seq_diff), seq_diff, null) asc,
          decode(seq_diff, abs(seq_diff), null, seq_diff) desc,
          abs(dist_diff); 

Этопорядок с помощью CASE:

order by  (case
             when seq_diff = abs(seq_diff) then seq_diff
             else null
           end) asc,
          (case
             when seq_diff = abs(seq_diff) then null
             else seq_diff
           end) desc,
           abs(dist_diff);

Ниже приведен результат для DECODE. (Я включил эти декодеры в выборку, чтобы увидеть значения).

Для положительных значений он сортируется по seq_ref asc, но затем для отрицательных значений он сортирует их также как asc, а не desc. И что странно в ряду 28-29, он идет desc, а затем снова asc.

DECODE

Порядок по CASE сортирует положительные значения по seq_ref asc и отрицательные значения desc, как и ожидалось. Это результат заказа по CASE:

CASE

Может кто-нибудь объяснить, почему это происходит с декодированием?

1 Ответ

2 голосов
/ 24 октября 2019

Я спросил, что это за тип данных, потому что сортировка выглядела как сортировка строк , а не чисел .

Посмотрите на это. Во-первых, только одно выражение в порядке по выражению:

SQL> with test (seq_diff) as
  2    (select -990 from dual union all
  3     select -610 from dual union all
  4     select -1350 from dual union all
  5     select -1340 from dual
  6    )
  7  select *
  8  from test
  9  order by decode(seq_diff, abs(seq_diff), seq_diff, null);

  SEQ_DIFF
----------
      -990
     -1340
     -1350
      -610

SQL>

Как они сортируются? Это не так. В соответствии с образцом набора данных, seq_diff не равно abs(seq_diff), поэтому порядок перемещается в null, что приводит к «случайным» упорядоченным значениям. Они вообще не сортируются.


Теперь давайте добавим еще один decode в порядок:

SQL> with test (seq_diff) as
  2    (select -990 from dual union all
  3     select -610 from dual union all
  4     select -1350 from dual union all
  5     select -1340 from dual
  6    )
  7  select *
  8  from test
  9  order by decode(seq_diff, abs(seq_diff), seq_diff, null),
 10           decode(seq_diff, abs(seq_diff), null, seq_diff) desc;

  SEQ_DIFF
----------
      -990
      -610
     -1350
     -1340

SQL>

Первый decode ничего не сделал, так какесли его не существует, мы переходим ко второму decode. Опять же, согласно набору данных, нет seq_diff равно abs(seq_diff), но на этот раз он возвращает seq_diff. Документация (как @krokodilko упомянул в своем комментарии) гласит:

  • Функция DECODE возвращает значение того же типа данных, что и первый результат в списке.
  • Еслипервый результат равен NULL, затем возвращаемое значение преобразуется в VARCHAR2.
    • это наш случай, поэтому возвращаемое значение (seq_diff) преобразуется в varchar2
  • Если первый результат имеет тип данных CHAR, возвращаемое значение преобразуется в VARCHAR2.
  • Если совпадений не найдено, возвращается значение по умолчанию.
  • Если по умолчаниюпропущен и совпадений не найдено, возвращается NULL.

Еще раз: наш случай второй:

decode(seq_diff, abs(seq_diff), null, seq_diff)
                                ----
                                the first result is NULL

Поэтому seq_diff преобразуется вСтрока и значения сортируются как таковые. Давайте проверим, что:

SQL> with test (seq_diff) as
  2    (select -990 from dual union all
  3     select -610 from dual union all
  4     select -1350 from dual union all
  5     select -1340 from dual
  6    )
  7  select *
  8  from test
  9  order by to_char(seq_diff) desc;

  SEQ_DIFF
----------
      -990
      -610
     -1350
     -1340

SQL>

Видите? Тот же самый результат, который мы получили с order by decode(seq_diff, abs(seq_diff), null, seq_diff) desc;


Последняя часть вашего предложения order by тривиальна (abs(dist_diff)), я думаю, объяснять это не нужно.


Вот почему вы получили странный результат с DECODE;на самом деле, это ожидаемое поведение.

...