Упорядочить по нескольким столбцам, игнорируя Null - PullRequest
0 голосов
/ 11 июня 2018

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

ITEM | At Loc1 | At Loc2 | At Loc3 | At Loc4 | Desired Order
--------------------------------------------------------
aaa  | 00:00   | 02:01   | NULL    | 05:30   | 0
bbb  | NULL    | 02:30   | 06:21   | NULL    | 1
ccc  | 00:05   | 02:33   | NULL    | 07:10   | 2 
ddd  | 00:07   | NULL    | 06:25   | 09:00   | 3
eee  | NULL    | NULL    | 06:30   | 09:10   | 4
fff  | 00:30   | 02:55   | 06:32   | NULL    | 5

Иногда время прибытия не записывается из-за ошибки измерения или неправильности.В этом случае время равно NULL

Теперь я хочу Select * from View ORDER BY AtLoc1 ASC, AtLoc2 ASC, AtLoc3 ASC, AtLoc4 ASC

Но нулевые значения в столбце не должны вызывать перемещение элемента вперед или назад.Он должен оставаться в правильном относительном положении в соответствии со следующим столбцом.

Например, элемент bbb не был записан в местоположении 1, но он прибыл в местоположение 2 после aaa и до ccc, поэтому его следует отсортироватьмежду aaa и ccc, а не в начале или в конце списка

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

Я не думаю, что смогу определить порядок сортировки, который является уникальным и четко определенным для всех особых случаев. Когда слишком много NULL сгруппированы вместе, тогда порядок может быть неопределенным.Но я просто хочу охватить наиболее распространенные случаи, когда нулевые значения относительно редки.

Как упорядочить представление в SQL таким образом?

Ответы [ 2 ]

0 голосов
/ 12 июня 2018

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

aaa     1      7
bbb  NULL      6
ccc     2      5

По сути, эти три вещи верны:

  • ccc> aaa
  • bbb> ccc
  • aaa> bbb

Все это не может быть истинным в одно и то же время (по крайней мере, не для чисел - или раз - как мы обычноиспользуйте их).

Хуан Карлос дает очень хорошее специальное решение, но оно не будет работать во всех случаях.

0 голосов
/ 11 июня 2018

Нужно больше тестов, но попробуйте это:

SQL DEMO

WITH cte as (
    SELECT *, 
           CASE WHEN [At Loc1] IS NOT NULL 
                THEN row_number() over (order by  [At Loc1] ) 
           END as r1,
           CASE WHEN [At Loc2] IS NOT NULL 
                THEN row_number() over (order by  [At Loc2] ) 
           END as r2,
           CASE WHEN [At Loc3] IS NOT NULL 
                THEN row_number() over (order by  [At Loc3] ) 
           END as r3,
           CASE WHEN [At Loc4] IS NOT NULL 
                THEN row_number() over (order by  [At Loc4] ) 
           END as r4
    FROM Table1
)
SELECT *, COALESCE(r1,r2,r3,r4)
FROM cte
ORDER BY COALESCE(r1,r2,r3,r4),
         COALESCE(r2,r3,r4),
         COALESCE(r3,r4),
         r4
;

ВЫХОД

enter image description here

...