Próbuję zamówić według daty. Chcę, aby najnowsze daty pojawiały się jako pierwsze. To dość proste, ale jest wiele rekordów, które są zerowe i poprzedzają jakiekolwiek rekordy z datą.
Próbowałem kilku rzeczy bez powodzenia:
ORDER BY ISNULL(Next_Contact_Date, 0)
ORDER BY ISNULL(Next_Contact_Date, 999999999)
ORDER BY coalesce(Next_Contact_Date, 99/99/9999)
Jak mogę porządkować według daty i mieć zerowe dane jako ostatnie? Typ danych to smalldatetime
.
sql-server
sql-server-2005
tsql
UpHelix
źródło
źródło
Odpowiedzi:
smalldatetime
ma zakres do 6 czerwca 2079 r., więc możesz użyćJeśli żadne legalne rekordy nie będą miały tej daty.
Jeśli nie jest to założenie, możesz polegać na bardziej niezawodnej opcji, czyli sortowaniu w dwóch kolumnach.
ORDER BY CASE WHEN Next_Contact_Date IS NULL THEN 1 ELSE 0 END, Next_Contact_Date
Obie powyższe sugestie nie pozwalają jednak na użycie indeksu, aby uniknąć sortowania i przedstawić podobnie wyglądające plany.
Jest jeszcze jedna możliwość, jeśli taki indeks istnieje
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
źródło
VARCHAR
pól (np.ORDER BY ISNULL(my_varchar, 'ZZZZZZ')
) I jest niezwykle przydatna, szczególnie do uzyskiwania zamówień w określony sposób podczas używaniaGROUP BY . . . GROUPING SETS
. Dzięki za opublikowanie tego.Według Itzika Ben-Gana, autora T-SQL Fundamentals for MS SQL Server 2012 , „Domyślnie SQL Server sortuje znaki NULL przed wartościami innymi niż NULL . Aby uzyskać znaki NULL do sortowania jako ostatnie, możesz użyć wyrażenia CASE, które zwraca 1, gdy kolumna „ Next_Contact_Date ma wartość NULL ” i 0, gdy nie jest równa NULL . Znaki inne niż NULL uzyskują 0 z powrotem z wyrażenia; dlatego są sortowane przed znakami NULL (które otrzymują 1). To wyrażenie CASE jest używane jako pierwsze sortowanie kolumny ”. Next_Contact_Datekolumna "powinna być określona jako druga kolumna sortowania. W ten sposób niż NULL będą znaczniki są sortowane poprawnie między sobą. ”Oto zapytanie rozwiązania dla Twojego przykładu dla MS SQL Server 2012 (i SQL Server 2014):
ORDER BY CASE WHEN Next_Contact_Date IS NULL THEN 1 ELSE 0 END, Next_Contact_Date;
Równoważny kod wykorzystujący składnię IIF:
źródło
Jeśli Twój SQL nie obsługuje
NULLS FIRST
lubNULLS LAST
, najprostszym sposobem na to jest użycievalue IS NULL
wyrażenia:aby umieścić null na końcu (
NULLS LAST
) lubaby umieścić wartości zerowe z przodu. Nie wymaga to znajomości typu kolumny i jest łatwiejsze do odczytania niż
CASE
wyrażenie.EDYCJA: Niestety, chociaż działa to w innych implementacjach SQL, takich jak PostgreSQL i MySQL, nie działa w MS SQL Server. Nie miałem serwera SQL do przetestowania i polegałem na dokumentacji firmy Microsoft oraz testach z innymi implementacjami SQL. Według Microsoftu
value IS NULL
jest to wyrażenie, które powinno być użyteczne tak jak każde inne wyrażenie. IORDER BY
ma przyjmować wyrażenia, tak jak każda inna instrukcja, która przyjmuje wyrażenie. Ale to tak naprawdę nie działa.Dlatego najlepszym rozwiązaniem dla SQL Server wydaje się być
CASE
wyrażenie.źródło
źródło
Next_Contact_Date
jest zerowyExplicit conversion from data type date to bigint is not allowed.
Trochę późno, ale może komuś się przyda.
Dla mnie ISNULL nie wchodziło w grę ze względu na skanowanie tabeli. UNION ALL wymagałoby powtórzenia złożonego zapytania, a ponieważ wybrałem tylko TOP X, nie byłoby to zbyt wydajne.
Jeśli jesteś w stanie zmienić projekt stołu, możesz:
Dodaj kolejne pole, tylko do sortowania, takie jak Next_Contact_Date_Sort.
Utwórz regułę, która wypełni to pole dużą (lub małą) wartością, w zależności od potrzeb:
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
źródło
Użyj desc i pomnóż przez -1, jeśli to konieczne. Przykład rosnącej kolejności int z zerami last:
select * from (select null v union all select 1 v union all select 2 v) t order by -t.v desc
źródło
Wiem, że to jest stare, ale to działa dla mnie
źródło