SQL 오름차순 정렬시 null 값을 마지막으로 만드는 방법


297

날짜 시간 필드가있는 SQL 테이블이 있습니다. 해당 필드는 null 일 수 있습니다. 쿼리가 있고 날짜 시간 필드별로 결과를 오름차순으로 정렬하고 싶지만 시작 시간이 아니라 목록의 끝에서 날짜 시간 필드가 null 인 행을 원합니다.

그것을 달성하는 간단한 방법이 있습니까?



답변:


394
select MyDate
from MyTable
order by case when MyDate is null then 1 else 0 end, MyDate

2
그러나 성능 (*)을 향상시키기 위해 정렬 열에 인덱스를 배치하면이 방법으로 인해 쿼리 계획이 다소 복잡해지고 성능상의 이점이 많이 손실됩니다. *-인덱스는 미리 정렬 된 데이터를 제공하므로 쿼리 당 정렬을 피합니다. 이 문제를 완전히 피하기 위해 가능하면 NULL 레코드를 필터링하는 것이 좋습니다.
redcalx

2
멋진 대답은 장점과 단점이 모든 가능한 방법으로 여기에 주어진 nickstips.wordpress.com/2010/09/30/...
sudhAnsu63

40
order by case when MyDate is null then 1 else 0 end정말 긴 말입니다ORDER BY MyDate IS NULL
Martin

5
@Martin이 질문은 mysql 태그가 없습니다. 나는 일반화 된 솔루션을 제공했습니다-다른 DB간에 동일한 일을하는 여러 가지 방법이 있습니다.
RedFilter

1
@KyleDelaney order by 0열 인덱스로 해석 되므로 열 인덱스는 1 기반입니다. 세 번째 열을 기준으로 쿼리를 정렬하려면 order by 3프로덕션 쿼리에 대한 끔찍한 아이디어 라고 할 수 있지만 *실험 할 때 매우 편리합니다 .
RedFilter

159

( "비트"늦었지만, 이것은 전혀 언급되지 않았습니다)

DBMS를 지정하지 않았습니다.

표준 SQL (및 Oracle, PostgreSQL, DB2, Firebird, Apache Derby, HSQLDB 및 H2와 같은 대부분의 최신 DBMS)에서 NULLS LAST또는 NULLS FIRST다음을 지정할 수 있습니다 .

NULLS LAST끝까지 정렬하는 데 사용하십시오 .

select *
from some_table
order by some_column DESC NULLS LAST

16
AFAIK NULLS FIRSTNULLS LASTSQL : 2003에 추가되었지만 다른 DMBS에서 사용할 수있는 표준 구현은 없습니다. 데이터베이스 엔진에 따라 ORDER BY expr some_column DESC NULLS LAST(Oracle), ORDER BY ISNULL(some_column, 1), some_column ASC(MSSQL) 또는 ORDER BY ISNULL(some_column), some_column ASC(다른 ISNULL () 구현으로 MySQL)을 사용하십시오.
SaschaM78

3
@ SaschaM78 : NULL의 기본 정렬은 DBMS에 따라 다릅니다. 일부는 끝에서 정렬하고 일부는 시작에서 정렬합니다. 일부는 약 귀찮게하지 않습니다 ASC/ DESC어떤이 할 null로. 따라서이를 보장하는 유일한 방법 은 DBMS 가이를 지원하는 NULL FIRST/LAST 경우 사용 하는 것입니다. 그것은 당신이 의도 한 것을 문서화 합니다. 의 사용 isnull()또는 다른 기능에 대한 누락 된 지원을위한 해결 방법입니다 NULLS FIRST/LAST(오라클, PostgreSQL을, DB2, 파이어 버드, 아파치 더비, HSQLDB와 H2로 suported됩니다)
a_horse_with_no_name

당신은 완벽하게 맞습니다. 저는 표준 (아직)을 따르지 않거나 exprNULLS FIRST / LAST를 사용할 때 키워드를 요구하는 Oracle과 같은 전문 지식이있는 DBMS가 있다는 사실을 추가하고 싶었습니다 . 그리고 데이터베이스 유형에 따라 null이 첫 번째 / 마지막으로 표시되는 것에 대해 감사합니다.
SaschaM78

2
이것은 유망 해 보이지만 슬프게도 시도했지만 NULLS LASTMySQL 데이터베이스에서 작동하지 않았습니다.
AdmiralThrawn

1
@AdmiralAdama : 항상 Postgres로 업그레이드 할 수 있습니다
a_horse_with_no_name

35

나는 또한 이것을 우연히 발견했으며 다음은 MySQL과 PostgreSQL에서 나를 위해 속임수를 쓰는 것처럼 보입니다.

ORDER BY date IS NULL, date DESC

에서 발견 https://stackoverflow.com/a/7055259/496209


이 모습은 유망하지만, 슬프게도, 나는 그것을 시도 IS NULL하고 IS NOT NULL내 MySQL 데이터베이스에 작업을하지 않았다.
AdmiralThrawn

14
order by coalesce(date-time-field,large date in future)

10
이것이 일반적으로 작동하지만이 답변에는 몇 가지 문제가 있습니다. 미래의 큰 날짜는 실제 데이터와 충돌하거나 실제 데이터보다 적을 수 있으므로 정렬이 불완전합니다. 또한 자체 문서화가 아닌 "매직 넘버"솔루션입니다.
RedFilter

이것은 문제의 열을 다른 날짜 열과 비교해야 할 때 @RedFilter 답변의 훌륭한 대안입니다. 나는 노조 선임 명단에 이것을 사용합니다. 직원이 정규화 된 날짜를 갖는 경우 (널 (NULL) 임) 해당 날짜가 맨 위에 기록됩니다. 그렇지 않으면 HireDate를 사용하십시오. ORDER BY ISNULL (QualifiedDate, '1-1-2099'), HireDate, LastName 등을 사용하면 적격 날짜가 HiredDate 날짜와 충돌하지 않고 올바른 Senirity 목록이 생성됩니다.
Alan Fisher

14

내장 함수를 사용하여 아래와 같이 null 여부를 확인할 수 있습니다. 나는 그것을 테스트하고 잘 작동합니다.

select MyDate from MyTable order by ISNULL(MyDate,1) DESC, MyDate ASC;


mssql과 함께 작동하는 날짜의 경우 ISNULL 함수에서 미래 날짜를 멀리하는 것이 유용하다는 것을 알았습니다. 즉 ISNULL (MyDate, '2100-01-01')
Emi-C

MySQL에서는 너무 많은 매개 변수를 전달한다고합니다. 이 작업을 수행하여 구문 분석 ISNULL(MyDate) DESC, MyDate ASC할 수 있지만 올바른 순서로 정렬되지 않았습니다.
AdmiralThrawn

12

엔진이 허용 ORDER BY x IS NULL, x하거나 ORDER BY x NULLS LAST사용하는 경우. 그러나 그것이 도움이되지 않으면 :

당신이 숫자 유형으로 분류하는 경우 당신은이 작업을 수행 할 수 있습니다 (에서 스키마를 빌려 다른 답변 .)

SELECT *          
FROM Employees
ORDER BY ISNULL(DepartmentId*0,1), DepartmentId;

마지막으로 null이있는 DepartmentId로 정렬 된 결과 표시

널이 아닌 숫자는 0이되고 널은 1이되어 널을 마지막으로 정렬합니다.

문자열에 대해서도이 작업을 수행 할 수 있습니다.

SELECT *
FROM Employees
ORDER BY ISNULL(LEFT(LastName,0),'a'), LastName

마지막 null이있는 성으로 정렬 된 결과 표시

때문에 'a'> ''.

이것은 nullable int로 강제하고 위의 ints 메소드를 사용하여 날짜와도 작동합니다.

SELECT *
FROM Employees
ORDER BY ISNULL(CONVERT(INT, HireDate)*0, 1), HireDate

스키마에 HireDate가 있다고 가정합니다.

이러한 방법은 데이터 유형 (및 최대)이 변경되면 (다른 ISNULL 솔루션이 겪는 문제 모두) 모든 유형의 "최대"값을 가져 오거나 관리해야하는 문제를 피하거나 쿼리를 수정합니다. 또한 CASE보다 훨씬 짧습니다.


잘 작동합니다! 감사합니다
Vani

8

주문 열에 순위와 같은 숫자가 있으면 -1을 곱한 다음 내림차순으로 정렬 할 수 있습니다. 그것은 당신이 소비하는 순서를 유지하지만 NULL을 마지막에 넣습니다.

select *
from table
order by -rank desc

이것에 대해 언급하려고했습니다. stackoverflow.com/a/8174026/1193304 에서 배웠으며 훌륭합니다.
Chris


3

nullable 날짜 시간 필드 정렬의 버그 문제에 대한 탁월한 솔루션을 제공 한 RedFilter에게 감사합니다.

프로젝트에 SQL Server 데이터베이스를 사용하고 있습니다.

datetime null 값을 '1'로 변경하면 datetime 데이터 유형 열의 정렬 문제가 해결됩니다. 그러나 datetime 데이터 유형 이외의 열이 있으면 처리하지 못합니다.

varchar 열 정렬을 처리하기 위해 열에 'Z'로 시작하는 값이 없다는 것을 알았으므로 'ZZZZZZZ'를 사용해 보았습니다. 예상대로 작동했습니다.

같은 줄에서 int 및 기타 데이터 유형에 대해 최대 값 +1을 사용하여 예상대로 정렬했습니다. 이것은 또한 나에게 필요한 결과를 주었다.

그러나 다음과 같은 작업을 수행 할 수있는 데이터베이스 엔진 자체에서 더 쉬운 것을 얻는 것이 항상 이상적입니다.

Order by Col1 Asc Nulls Last, Col2 Asc Nulls First 

a_horse_with_no_name이 제공 한 답변에서 언급했듯이.



3

MariaDB를 사용하는 경우 NULL 값 설명서 에서 다음을 언급합니다 .

발주

NULL 값을 포함 할 수있는 필드를 기준으로 정렬하면 모든 NULL 값이 가장 낮은 것으로 간주됩니다. 따라서 DESC 순서로 주문하면 NULL이 마지막에 나타납니다. NULL을 최고 값으로 간주하기 위해 기본 필드가 NULL 일 때 더 높은 값을 갖는 다른 열을 추가 할 수 있습니다. 예:

SELECT col1 FROM tab ORDER BY ISNULL(col1), col1;

내림차순, 먼저 NULL

SELECT col1 FROM tab ORDER BY IF(col1 IS NULL, 0, 1), col1 DESC;

DISTINCT 및 GROUP BY 절의 목적 상 모든 NULL 값도 동등한 것으로 간주됩니다.

위의 두 가지 방법으로 NULL 값을 정렬 할 수 있으며 ASC 및 DESC 키워드와 함께 조합 할 수도 있습니다. 예를 들어 NULL 값을 먼저 얻는 다른 방법은 다음과 같습니다.

SELECT col1 FROM tab ORDER BY ISNULL(col1) DESC, col1;
--                                         ^^^^

2

"case"를 사용하는 솔루션은 보편적이지만 색인을 사용하지 마십시오.

order by case when MyDate is null then 1 else 0 end, MyDate

제 경우에는 성능이 필요했습니다.

 SELECT smoneCol1,someCol2  
 FROM someSch.someTab
 WHERE someCol2 = 2101 and ( someCol1 IS NULL ) 
  UNION   
 SELECT smoneCol1,someCol2
 FROM someSch.someTab
 WHERE someCol2 = 2101 and (  someCol1 IS NOT NULL)  

1
성능에 관심이 있다면를 사용해야합니다 UNION ALL.
RedFilter


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