[sql-server] SQL Server ORDER BY 날짜 및 null 마지막

날짜별로 주문하려고합니다. 가장 최근 날짜가 먼저 나오길 원합니다. 간단하지만 null 인 레코드가 많고 날짜가있는 레코드 앞에 오는 레코드가 많습니다.

몇 가지 시도했지만 성공하지 못했습니다.

ORDER BY ISNULL(Next_Contact_Date, 0)

ORDER BY ISNULL(Next_Contact_Date, 999999999)

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

날짜별로 주문하고 null이 마지막에 오도록하려면 어떻게해야합니까? 데이터 유형은 smalldatetime입니다.



답변

smalldatetime 2079 년 6 월 6 일까지 범위가 있으므로

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

위의 두 제안 모두 색인을 사용하여 정렬을 피하고 비슷한 계획을 제공 할 수 없습니다.

여기에 이미지 설명 입력

그러한 인덱스가 존재한다면 또 다른 가능성은

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

계획


답변

Itzik 벤 웨이 코 뮤니시의 저자에 따르면, MS SQL 서버 2012 T-SQL 기본 기본적으로, “SQL 서버는 정렬 NULL의 비 전에 마크를 NULL의 값. 얻으려면 NULL의 마크가 마지막으로 정렬, 당신은 사용할 수있는 사례 가 반환하는 식을 1 ‘경우 Next_Contact_Date 열은 NULL 이 아닌 경우 0 ” NULL 비. NULL의 표시가 발현 0 다시 얻기 때문에, 그들은 정렬 전에 부호 (어느 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;


답변

당신의 SQL을 지원하지 않는 경우 NULLS FIRSTNULLS LAST,이 작업을 수행하는 가장 간단한 방법은 사용하는 것입니다 value IS NULL표현 :

ORDER BY Next_Contact_Date IS NULL, Next_Contact_Date

끝에 null을 넣으려면 ( NULLS LAST) 또는

ORDER BY Next_Contact_Date IS NOT NULL, Next_Contact_Date

널을 앞에 놓으십시오. 이것은 열의 유형을 알 필요가 없으며 CASE표현식 보다 읽기 쉽습니다 .

편집 : 아아, 이것은 PostgreSQL 및 MySQL과 같은 다른 SQL 구현에서 작동하지만 MS SQL Server에서는 작동하지 않습니다. 저는 테스트 할 SQL Server가 없었고 Microsoft의 문서에 의존하고 다른 SQL 구현으로 테스트했습니다. Microsoft에 따르면는 다른 표현처럼 사용할 수 있어야 value IS NULL 하는 표현 입니다. 그리고 ORDER BY 표현을 취해야합니다 다른 진술과 마찬가지로 합니다. 그러나 실제로 작동하지 않습니다.

따라서 SQL Server에 대한 최상의 솔루션은 CASE식인 것 같습니다.


답변

order by -cast([Next_Contact_Date] as bigint) desc


답변

조금 늦었지만 누군가 유용하다고 생각할 수도 있습니다.

나에게 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
    


답변

desc를 사용하고 필요한 경우 -1을 곱합니다. 마지막에 null이있는 오름차순 int 순서의 예 :

select *
from
(select null v union all select 1 v union all select 2 v) t
order by -t.v desc


답변

나는 이것이 오래되었다는 것을 알고 있지만 이것이 나를 위해 일한 것입니다.

Order by Isnull(Date,'12/31/9999')