sqld

SQLD 정렬 정리

noAb 2024. 10. 29. 11:54

SQLD방에서 관리자로 활동을 하다보면 정렬에 대해 어려움을 느끼는분이 많아서 보기쉽게 정리해보려고합니다.

기본적으로 정렬이라고 한다면 데이터들을 출력할때 오름차순, 내림차순을 할 때 사용을 합니다.

예시들을 보시면서 같이 보시죠


기본 정렬 

<회원 테이블>

name age
kim 20
lea 21

회원 테이블에 이름나이 속성이 있고, kim과 lea회원이 있을때 이름을 기준으로 정렬을 해보겠습니다.

select name, age from 회원 order by name asc
name age
kim 20
lea 21

- order by에 기본은 오름차순이므로 asc는 생략이 가능합니다. 반대로 얘기하면 desc나 asc가 없다면 자동으로 asc오름차순이란 의미입니다.

select name, age from 회원 order by name desc
name age
lea 21
kim 20
이름으로 정렬했을때 알파벳 순서대로 a부터 z까지 나열했을때 a가 가장 낮고 z가 제일 높다고 판단하여
오름차순일 경우 낮은 k인 kim이 먼저 나오고 높은 l인 lea가 나오게 됩니다. 
반대로 내림차순일땐 높은값이 먼저 나오기 때문에 l인 lea가 먼저 나오는 모습입니다.

ORDER BY가 2개 이상일 때

<성적 테이블>

name english math
lea A C
park B D
ryu C B
kim A A

성적 테이블에 4명 학생에 대한 성적데이터가 들어있습니다. 이때 영어성적으로 정렬을 하고 만약 같은 성적이 있다면 수학으로 다시 정렬을 하는 쿼리입니다.

select name, english, math from 성적 order by english asc, math
name english math
kim A A
lea A C
park B D
ryu C B

쿼리에서 정렬부분을 보게 되면 영어 성적을 오름차순을 먼저하고 만약 같은 영어 성적이 같은 학생이 존재한다면 그 학생들 안에서 다시 수학으로 오름차순을 하는 모습입니다. 만약 영어 성적이 같은 학생이 없다면 수학정렬은 사실상 필요없게 될겁니다.


정렬할 컬럼에 NULL이 있는 상황

<회원 테이블>

name age hobby
kim 20 study
lea 27 codding
park 21  
ryu 20 running

현재 회원테이블에는 이름과 나이, 취미 컬럼이 있을때 park에 취미는 NULL인 상황입니다.

기본적으로 SQLD에서는 오라클과, SQL SERVER를 사용하는데 가끔 문제를 읽다보면 어떤 DBMS인지 알려주고 풀어야하는 문제가 존재합니다. 이번 예제처럼 정렬에 NULL이 존재할때가 그럴때 입니다. 

오라클에서 NULL은 가장큰값으로 간주하고, SQL SERVER에서는 가장 작은 값으로 간주합니다. 

select name, age, hobby from 회원 order by hobby asc

- 오라클

name age hobby
lea 27 codding
ryu 20 running
kim 20 study
park 21  

 

- SQL SERVER

name age hobby
park 21  
lea 27 codding
ryu 20 running
kim 20 study

 이처럼 같은 정렬을 하더라도 NULL에 위치가 달라지는 모습을 보입니다.


ORDER BY에 숫자가 있을 때

<회원 테이블>

name age hobby
kim 20 study
lea 27 codding
park 21  
ryu 20 running

기본적으로 정렬구문에는 기준이 되는 컬럼명을 작성하지만 숫자가 들어가는 상황도 존재합니다.

SELECT NAME, AGE, HOBBY FROM 회원 ORDER BY 1 asc, 2 desc

위에 쿼리처럼 1오름차순, 2내림차순으로도 사용이 가능합니다.

해당 숫자는 SELECT에 오는 컬럼들의 순서를 의미합니다. 즉 1은 SELECT에서 명시된 첫번째 컬럼인 NAME을 의미하고 2는 두번째인 AGE를 의미하게 됩니다.

SELECT NAME, AGE, HOBBY FORM 회원 ORDER BY NAME ASC, AGE DESC

쿼리에 숫자 대신 컬럼명을 대입해보면 위와 같은 의미가 되게 됩니다.

name age hobby
kim 20 study
lea 27 codding
park 21  
ryu 20 running

이름대로 오름차순이 된 결과 모습입니다. 사실상 2인 age는 사용되지 않은 모습입니다.


ORDER BY에 함수가 있을때

SQLD를 공부하기위해 노랭이라는 책을 풀다보면 ORDER BY에 CASE문이 있는 문제를 보시게 될겁니다.

COL1 COL2
1 999
1 1
2 999
2 2

 

SELECT COL1, COL2 FROM TABLE ORDER BY (CASE WHEN COL2 = 999 THEN 1 ELSE 0 END), COL1 DESC

ORDER BY는 해당 컬럼의 값으로 비교를 하게 되는데 이처럼 CASE문이 들어갈경우 해당 컬럼을 대입해서 나온 값으로 비교를 해서 정렬을 하게 됩니다. 

현재 4개의 데이터 행이 존재하는데 이중 COL2컬럼이 999라면 1 아니라면 0으로 취급하여 오름차순을 하고, 그 안에서 같은 값이 존재할때 다시 COL1로 내림차순을 하시면 됩니다.

  1. 네개의 데이터행중에서 첫번째, 세번째 행에 COL2값이 999이므로 1, 두번째, 네번째 행이 0으로 취급
  2. 오름차순이므로 두번째행과 네번째 행이 0이기 때문에 먼저 나오는데 값이 같기 때문에 다시 COL1로 내림차순을 하여 네번째 행이 먼저 나오고 두번째 행이 다음에 나옵니다.
  3. 이어서 첫번째 행과 세번째 행이 나오는데 둘이 같은 1이므로 다시 COL1로 내림차순을 하여 세번째 행이 먼저 나오고 첫번째 행이 나오게 됩니다.
COL1 COL2
2 2
1 1
2 999
1 999

UNION으로 합친 결과에서 ORDER BY할 때

UNION같이 두결과를 합쳐서 출력하는 쿼리가 있다면 방법은 동일하지만 주의해야할 점이 몇가지 존재합니다.

  1. ORDER BY는 가장 아래 쿼리에만 들어가야한다.
  2. ORDER BY에 정렬 컬럼은 가장 최상단 쿼리에 SELECT를 기준으로 한다.

정렬을 하는 방법은 동일하므로 따로 예시는 필요없지만 위에 두가지 주의사항만 아신다면 쉽게 풀이가 가능합니다.