SQL Server ORDER BY дата и нули последние - PullRequest
69 голосов
/ 04 мая 2011

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

Я попробовал несколько вещей без успеха:

ORDER BY ISNULL(Next_Contact_Date, 0)

ORDER BY ISNULL(Next_Contact_Date, 999999999)

ORDER BY coalesce(Next_Contact_Date, 99/99/9999)

Как я могу сделать заказ по дате и получить нулевые значения последними? Тип данных smalldatetime.

Ответы [ 7 ]

98 голосов
/ 04 мая 2011

smalldatetime имеет диапазон до 6 июня 2079 года, поэтому вы можете использовать

ORDER BY ISNULL(Next_Contact_Date, '2079-06-05T23:59:00')

Если никакие законные записи не будут иметь эту дату.

Если это не предположение, вы предпочитаете полагаться на более надежный вариант сортировки по двум столбцам.

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

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

enter image description here

Еще одна возможность, если такой индекс существует, -

SELECT 1 AS Grp, Next_Contact_Date 
FROM T 
WHERE Next_Contact_Date IS NOT NULL
UNION ALL
SELECT 2 AS Grp, Next_Contact_Date 
FROM T 
WHERE Next_Contact_Date IS NULL
ORDER BY Grp, Next_Contact_Date

Plan

24 голосов
/ 06 мая 2016

По словам Ицик Бен-Гана, автора Основы T-SQL для MS SQL Server 2012 , "По умолчанию SQL Server сортирует отметки NULL доне- NULL значений. Чтобы получить NULL меток для сортировки в последний раз, вы можете использовать CASE выражение, которое возвращает 1, когда столбец " Next_Contact_Date равен NULL ," и 0, если он не NULL . Номера- NULL возвращают 0 из выражения, поэтому они сортируются до NULL отметок (которые получают 1). Это выражение CASE используется в качестве первого столбца сортировки. "В качестве второго столбца сортировки должен быть указан столбец Next_Contact_Date . Таким образом, отличные от NULL столбцы сортируются между собой. "Вот запрос решения для вашего примера для MS SQL Server 2012 (и SQL Server 2014):

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

Эквивалентный код с использованием синтаксиса IIF:

ORDER BY 
   IIF(Next_Contact_Date IS NULL, 1, 0),
   Next_Contact_Date;
2 голосов
/ 08 января 2015
order by -cast([Next_Contact_Date] as bigint) desc
2 голосов
/ 29 апреля 2014

Немного поздно, но, возможно, кто-то найдет это полезным.

Для меня ISNULL был вне вопроса из-за сканирования таблицы.UNION ALL потребовалось бы, чтобы я повторил сложный запрос, и из-за того, что я выбрал только TOP X, это было бы не очень эффективно.

Если вы можете изменить дизайн таблицы, вы можете:

  1. Добавить еще одно поле для сортировки, например Next_Contact_Date_Sort.

  2. Создать триггер, который заполняет это поле большим (или небольшим) значением, в зависимости отна что нужно:

    CREATE TRIGGER FILL_SORTABLE_DATE ON YOUR_TABLE AFTER INSERT,UPDATE AS 
    BEGIN
        SET NOCOUNT ON;
        IF (update(Next_Contact_Date)) BEGIN
        UPDATE YOUR_TABLE SET Next_Contact_Date_Sort=IIF(YOUR_TABLE.Next_Contact_Date IS NULL, 99/99/9999, YOUR_TABLE.Next_Contact_Date_Sort) FROM inserted i WHERE YOUR_TABLE.key1=i.key1 AND YOUR_TABLE.key2=i.key2
        END
    END
    
1 голос
/ 17 августа 2014

Используйте desc и умножьте на -1, если необходимо. Пример упорядочения по возрастанию с нулями last:

select * 
from
(select null v union all select 1 v union all select 2 v) t
order by -t.v desc
1 голос
/ 31 июля 2013

Если ваш SQL не поддерживает NULLS FIRST или NULLS LAST, самый простой способ сделать это - использовать выражение value IS NULL:

ORDER BY Next_Contact_Date IS NULL, Next_Contact_Date

, чтобы поставить нулевые значения в конце (NULLS LAST) или

ORDER BY Next_Contact_Date IS NOT NULL, Next_Contact_Date

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

РЕДАКТИРОВАТЬ: Увы, хотя это работает в других реализациях SQL, таких как PostgreSQL и MySQL, оно не работаетв MS SQL Server.У меня не было SQL Server для тестирования, и я полагался на документацию Microsoft и тестирование с другими реализациями SQL.Согласно Microsoft, value IS NULL - это выражение , которое должно использоваться как любое другое выражение.И ORDER BY должен принимать выражения , как и любой другой оператор, который принимает выражение.Но на самом деле это не работает.

Таким образом, лучшим решением для SQL Server является выражение CASE.

0 голосов
/ 11 сентября 2018

Я знаю, что это старо, но это то, что у меня сработало

Order by Isnull(Date,'12/31/9999')
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...