SQL Server ORDER BY 날짜 및 null 마지막


82

날짜별로 주문하려고합니다. 가장 최근 날짜가 먼저 나오길 원합니다. 간단하지만 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입니다.


정렬 순서는 오름차순이어야하지만 끝에 널이 있어야합니까? 그리고 테이블에 미래 날짜가 있습니까?
AllenG 2011 년

@AllenG, 예, 과거부터 미래까지 과거를 먼저 등으로. 그래, 오름차순. 예, 미래의 날짜는 대부분의 날짜입니다.
UpHelix 2011 년

답변:


112

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

계획


이 트릭은 VARCHAR필드 에도 적용 할 수 있으며 (예 ORDER BY ISNULL(my_varchar, 'ZZZZZZ'):) 특히를 사용할 때 특정 방식으로 주문을받는 데 매우 유용합니다 GROUP BY . . . GROUPING SETS. 게시 해 주셔서 감사합니다.
sparc_spread

desc에 의한 순서를 사용하여 하단에 null을 넣을 수없는 이유는 무엇입니까? 또한 null을 1로 매핑하는 이유는 무엇입니까?
MasterJoe

35

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;

또한 대답에 추가하려면 IIF의 1과 0을 전환하면 null이 맨 위로 이동합니다. 이것은 테이블 상단에 배치하여 단일 출력 튜플을 원하는 경우에도 작동합니다.
Franco Pettigrosso

3

당신의 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식인 것 같습니다.


7
이것은 유효한 SQL Server 구문이 아닙니다
Martin Smith

3
미안합니다. 그것은 해야 Microsoft 설명서 및 기타 SQL을의 작품 당 유효하지만, MS는 실제로 그것을 허용하지 않습니다.
Vroo 2013-08-22

성능 현명한 이건 끔찍하게 들리는데 2 개의 정렬 기준을 수행하고 있습니다
ColacX

링크 한 Microsoft 문서에서 IS NULL 값표현식 이 아니라 조건 자임을 읽었습니다 . 이건 같은게 아니야.
BertuPG

1
Microsoft에 따르면 술어는 표현식입니다. 말 그대로 docs.microsoft.com/en-us/sql/t-sql/queries/predicates
Vroo

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

Next_Contact_Datenull 인 경우 오류 발생Explicit conversion from data type date to bigint is not allowed.
Nerdroid

2

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

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

2

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

이 날짜 같은 변수 일 것이라고 생각하지 마십시오 ..
샬롯 덩 샤오핑에게

1

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

Order by Isnull(Date,'12/31/9999')
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.