Menu

SQLite ORDER BY 사용법: 정렬, DESC, 다중 컬럼

SQLite의 ORDER BY로 결과를 정렬하는 방법을 정리합니다. 오름차순/내림차순, 여러 컬럼으로 정렬, NULL 위치 제어, 대소문자 무시 정렬까지 한 번에 살펴봅니다.

이 페이지에는 실행 가능한 에디터가 있습니다 — 편집하고 실행하면 결과를 바로 볼 수 있습니다.

ORDER BY 없이는 행의 순서를 보장할 수 없다

ORDER BY 없이 SELECT을 실행하면 SQLite는 그저 자기에게 편한 순서로 행을 돌려준다. 작은 테이블에서는 마치 입력한 순서대로 나오는 것처럼 보이기 때문에 이걸 믿게 되기 쉽다. 하지만 절대 믿으면 안 된다. 인덱스가 쓰이는 순간, 또는 테이블이 커지거나 쿼리 플랜이 달라지는 순간, 그 순서는 예고 없이 바뀔 수 있다.

행의 순서가 중요하다면, 반드시 명시적으로 적어 주자:

ORDER BY name은 기본적으로 오름차순으로 정렬합니다. 결과는 항상 Ada, Boris, Chen, Rosa 순서로, 즉 알파벳 순서대로 나옵니다. 테이블이 디스크에 어떤 순서로 저장돼 있든 상관없죠.

ASC와 DESC로 정렬 방향 정하기

ASC는 오름차순(작은 값 → 큰 값, A → Z, 과거 → 최근)을 뜻하고, DESC는 그 반대인 내림차순을 뜻합니다. ASC가 기본값이라 실제 코드에서는 거의 생략하고 씁니다:

가장 최근에 가입한 사용자부터 보여주는 쿼리입니다. ISO 8601 형식(YYYY-MM-DD) 문자열로 저장된 날짜는 텍스트로 정렬해도 순서가 정확하게 맞아떨어지는데요. SQLite에는 별도의 날짜 타입이 없기 때문에, 날짜 컬럼에 이 형식을 권장하는 이유 중 하나가 바로 이것입니다.

SQLite 여러 컬럼으로 정렬하기

첫 번째 정렬 기준에서 값이 같은 행이 나오면, SQLite는 두 번째 컬럼을 보고 순서를 정합니다. 우선순위가 높은 컬럼부터 쉼표로 구분해서 나열하면 됩니다.

행을 먼저 국가별로 묶은 뒤(FRUS보다 먼저 나옵니다), 같은 국가 안에서는 이름 순으로 정렬됩니다. 각 컬럼마다 정렬 방향을 따로 지정할 수 있습니다:

국가 이름은 오름차순으로, 같은 국가 안에서는 최신 항목이 먼저 오도록 정렬하는 식입니다. ASCDESC는 바로 옆에 있는 컬럼에만 적용된다는 점을 꼭 기억하세요. 다음 컬럼까지 따라가지 않습니다.

표현식과 별칭으로 정렬하기

ORDER BY에는 컬럼명뿐 아니라 어떤 표현식이든 넣을 수 있습니다. 계산된 값을 기준으로 정렬할 때 특히 유용하죠.

SELECT 절에서 만든 revenue 같은 별칭은 ORDER BY에서 그대로 써도 됩니다. 굳이 별칭 대신 ORDER BY price * quantity DESC처럼 식을 다시 풀어 써도 결과는 똑같고요.

컬럼 위치(번호)로 정렬하는 방법도 있긴 한데, 가급적 쓰지 않는 게 좋습니다:

SELECT name, price FROM products ORDER BY 2 DESC;

2는 select 목록에서 두 번째 컬럼을 의미합니다. 동작은 하지만, 누군가 나중에 컬럼 순서를 바꾸면 정렬 기준도 조용히 바뀌어 버립니다. 그러니 컬럼명이나 별칭(alias)으로 정렬하세요.

NULL은 어디에 정렬될까

NULL은 "알 수 없음"을 뜻하기 때문에, SQLite는 정렬할 때 이 값들을 어디에 둘지 결정해야 합니다. 기본 규칙은 이렇습니다. ASC에서는 NULL이 맨 앞, DESC에서는 맨 뒤에 옵니다.

Ada와 Chen이 실제 날짜보다 앞쪽에 올라와 버리죠. "최신순으로 보기" 같은 의도와는 거리가 멉니다. 이럴 때는 NULLS LAST로 동작 방식을 바꿔주면 됩니다:

이렇게 하면 실제 날짜가 먼저 오고 NULL 값은 맨 아래로 밀립니다. 반대로 NULLS FIRST를 쓰면 NULL이 먼저 나오죠. 둘 다 표준 SQL 문법이고, SQLite 3.30 이상에서 동작합니다.

COLLATE NOCASE로 대소문자 구분 없이 정렬하기

SQLite의 기본 텍스트 비교 방식은 바이너리(binary)입니다. 즉, 유니코드 코드 포인트 순서로 정렬하죠. 그래서 대문자가 소문자보다 앞쪽 으로 가서, 'Zoe''apple'보다 먼저 나오는 상황이 벌어집니다:

결과는 Boris, Zoe, ada, apple처럼 대문자가 먼저 오고 소문자가 뒤따르는 순서로 정렬됩니다. 대소문자 구분 없이 정렬하려면 NOCASE 콜레이션을 붙여 주세요:

이렇게 하면 결과가 ada, apple, Boris, Zoe 순으로 나옵니다. NOCASE는 ASCII 영문자 A–Z와 a–z만 같은 문자로 취급할 뿐, 악센트가 붙은 문자나 비ASCII 문자는 정규화하지 않는다는 점을 기억해 두세요. 진짜 다국어 정렬이 필요하다면 애플리케이션 레벨에서 별도의 collation을 구현해야 하지만, 영어 위주의 일반적인 상황이라면 NOCASE만으로도 충분합니다.

무작위 순서로 정렬하기

가끔은 행을 랜덤한 순서로 가져오고 싶을 때가 있습니다. 매일 바뀌는 추천 항목을 뽑거나, 테스트용으로 행을 샘플링하는 경우가 대표적이죠. 이럴 때는 SQLite의 random() 함수가 정수 난수를 반환하니, 이 값을 기준으로 정렬하면 됩니다:

행마다 새로운 난수가 매겨지고, 그 값을 기준으로 섞이는 방식입니다. 데이터가 적다면 문제없지만, 큰 테이블에서는 ORDER BY random()이 느립니다. 모든 행에 대해 난수를 계산한 뒤 결과 전체를 정렬해야 하기 때문이죠. 거대한 테이블에서 한 행만 무작위로 뽑고 싶다면, rowid를 임의로 골라오는 식의 더 영리한 접근이 훨씬 빠릅니다.

자주 하는 실수

이런 부분에서 많이 걸려 넘어집니다.

  • ORDER BY를 빼놓고 순서를 가정하기. 정렬 절이 없으면 결과 순서는 보장되지 않습니다. 안정적으로 보여도 사실은 그렇지 않아요.
  • 숫자를 문자열로 저장한 채 정렬하기. 사전순으로 비교하면 '10''2'보다 앞섭니다. 숫자처럼 정렬해야 하는 컬럼이라면 숫자 affinity로 저장하거나, ORDER BY CAST(value AS INTEGER)처럼 캐스팅하세요.
  • 여러 컬럼에 ASC와 DESC를 섞을 때. sqlite 여러 컬럼 정렬에서는 각 컬럼마다 방향을 따로 지정해야 합니다. ORDER BY a, b DESCa는 오름차순, b만 내림차순으로 정렬합니다. 둘 다 내림차순이 아니에요.
  • 상위 몇 개만 필요한데 전체 결과를 정렬하기. ORDER BYLIMIT과 함께 쓰고, 정렬 컬럼에 인덱스를 걸어두세요. 바로 다음 주제입니다.

다음: LIMIT과 OFFSET

ORDER BY가 SQLite에 행을 어떻게 배열할지 알려준다면, LIMITOFFSET얼마나 반환하고 어디서부터 시작할지 알려줍니다. 이 둘을 합치면 페이지네이션과 "상위 N개" 쿼리의 핵심이 완성되죠. 다음 장에서 이어집니다.

자주 묻는 질문

SQLite에서 결과를 정렬하려면 어떻게 하나요?

SELECT 문 끝에 ORDER BY 절을 붙이고 정렬할 컬럼을 적으면 됩니다. 예를 들어 SELECT * FROM users ORDER BY name;은 오름차순으로 정렬되고, 내림차순으로 바꾸려면 ORDER BY name DESC처럼 DESC를 붙이면 됩니다. ORDER BY를 쓰지 않으면 행의 순서는 보장되지 않으니, 결과가 일정하게 보이더라도 절대 그 순서에 의존하면 안 됩니다.

SQLite에서 여러 컬럼으로 정렬하려면 어떻게 하나요?

콤마로 구분해서 나열하면 됩니다. ORDER BY country, name처럼 쓰면 SQLite는 먼저 country로 정렬한 뒤 같은 값이 있을 때 name으로 다시 정렬합니다. 컬럼별로 방향도 따로 지정할 수 있어서, ORDER BY country ASC, signup_date DESC처럼 섞어 쓸 수도 있습니다.

SQLite에서 대소문자 구분 없이 정렬하려면 어떻게 하나요?

ORDER BYCOLLATE NOCASE를 붙이면 됩니다. 예: ORDER BY name COLLATE NOCASE. SQLite는 기본적으로 텍스트를 바이너리 방식으로 비교하기 때문에 Zoeapple보다 앞에 옵니다. NOCASE를 쓰면 대문자와 소문자를 같은 것으로 취급해서 정렬합니다.

정렬한 결과에서 NULL 값은 어디에 위치하나요?

기본 동작은 오름차순일 때 NULL이 맨 앞, 내림차순일 때 맨 뒤에 옵니다. 이 동작을 바꾸려면 NULLS FIRST 또는 NULLS LAST를 명시하면 됩니다. 예를 들어 ORDER BY signup_date DESC NULLS LAST로 쓰면 실제 날짜 값이 위쪽에 오고 NULL은 맨 아래로 밀려납니다.

Coddy programming languages illustration

Coddy로 코딩 배우기

시작하기