SELECT 절

SELECT 절 (SELECT Clause)

SELECT 절은 쿼리가 반환할 열 목록을 지정해요. 절의 맨 앞에 나타나지만, 논리적으로 여기의 표현식들은 마지막에만 실행돼요. SELECT 절은 출력을 변환하는 임의의 표현식뿐만 아니라 집계 함수와 윈도우 함수도 포함할 수 있어요.

출처: DuckDB 공식 문서 — SELECT Clause

예제 (Examples)

tbl 테이블의 모든 열을 선택해요:

SELECT * FROM tbl;

테이블 열에 산술 연산을 수행하고 별칭(alias)을 제공해요:

SELECT col1 + col2 AS res, sqrt(col1) AS root FROM tbl;

접두사 별칭(prefix aliases)을 사용해요:

SELECT
    res: col1 + col2,
    root: sqrt(col1)
FROM tbl;

addresses 테이블에서 모든 고유한 도시를 선택해요:

SELECT DISTINCT city FROM addresses;

addresses 테이블의 총 행 수를 반환해요:

SELECT count(*) FROM addresses;

addresses 테이블에서 city 열을 제외한 모든 열을 선택해요:

SELECT * EXCLUDE (city) FROM addresses;

addresses 테이블의 모든 열을 선택하되, citylower(city)로 대체해요:

SELECT * REPLACE (lower(city) AS city) FROM addresses;

정규식과 일치하는 모든 열을 테이블에서 선택해요:

SELECT COLUMNS('number\d+') FROM addresses;

테이블의 주어진 모든 열에 함수를 계산해요:

SELECT min(COLUMNS(*)) FROM addresses;

공백이나 특수 문자가 있는 열을 선택하려면 큰따옴표(")를 사용해요:

SELECT "Some Column Name" FROM tbl;

SELECT 목록 (The Select List)

SELECT 절은 쿼리의 결과를 지정하는 표현식 목록을 포함해요. select 목록은 FROM 절의 어떤 열이든 참조할 수 있고, 표현식을 사용해 결합할 수 있어요. SQL 쿼리의 출력은 테이블이므로, SELECT 절의 모든 표현식에도 이름이 있어요. 표현식은 AS 절을 사용해 명시적으로 이름을 붙일 수 있어요 (예: expr AS name). 사용자가 이름을 제공하지 않으면 시스템이 자동으로 이름을 붙여요.

열 이름은 대소문자를 구분하지 않아요. 자세한 내용은 대소문자 구분 규칙을 참고하세요.

별 표현식 (Star Expressions)

tbl 테이블의 모든 열을 선택해요:

SELECT *
FROM tbl;

정규식과 일치하는 모든 열을 테이블에서 선택해요:

SELECT COLUMNS('number\d+')
FROM addresses;

별 표현식(star expression)FROM 절의 내용에 기반해 여러 표현식으로 확장되는 특별한 표현식이에요. 가장 단순한 경우, *FROM 절의 모든 표현식으로 확장돼요. 열은 정규식이나 람다 함수를 사용해서도 선택할 수 있어요. 자세한 내용은 별 표현식 페이지를 참고하세요.

DISTINCT

addresses 테이블의 모든 고유한 도시를 선택해요:

SELECT DISTINCT city
FROM addresses;

DISTINCT 절은 결과에서 오직 고유한 행만 반환하는 데 사용돼요 — 중복 행이 걸러지죠.

SELECT DISTINCT로 시작하는 쿼리는 중복 제거(deduplication)를 수행하며, 이는 비용이 큰 연산이에요. 따라서 필요한 경우에만 DISTINCT를 사용하세요.

DISTINCT ON

각 국가에서 인구가 가장 많은 도시만 선택해요:

SELECT DISTINCT ON(country) city, population
FROM cities
ORDER BY population DESC;

DISTINCT ON 절은 ON 절에 정의된 표현식 집합의 고유 값마다 하나의 행만 반환해요. ORDER BY 절이 있으면, 반환되는 행은 ORDER BY 기준에 따라 처음 만나는 행이에요. ORDER BY 절이 없으면, 처음 만나는 행은 정의되지 않으며 테이블의 어떤 행이든 될 수 있어요.

대규모 데이터셋을 쿼리할 때, 모든 열에 DISTINCT를 사용하는 것은 비용이 클 수 있어요. 따라서 결과에 충분한 고유성을 보장하는 열(또는 열 집합)에 DISTINCT ON을 사용하는 것을 고려해보세요. 예를 들어 테이블의 키 열에 DISTINCT ON을 사용하면 완전한 고유성이 보장돼요.

집계 (Aggregates)

addresses 테이블의 총 행 수를 반환해요:

SELECT count(*)
FROM addresses;

도시별로 그룹화된 addresses 테이블의 총 행 수를 반환해요:

SELECT city, count(*)
FROM addresses
GROUP BY city;

집계 함수(aggregate functions)는 여러 행을 결합하여 단일 값으로 만드는 특별한 함수예요. SELECT 절에 집계 함수가 있으면 쿼리는 집계 쿼리로 변환돼요. 집계 쿼리에서 모든 표현식은 집계 함수의 일부이거나, GROUP BY 절로 지정된 그룹의 일부여야 해요.

윈도우 함수 (Window Functions)

각 행에 증분 식별자를 포함하는 row_number 열을 생성해요:

SELECT row_number() OVER ()
FROM sales;

시간 순서대로 현재 금액과 이전 금액의 차이를 계산해요:

SELECT amount - lag(amount) OVER (ORDER BY time)
FROM sales;

윈도우 함수(window functions)는 결과에서 다른 행에 상대적인 값을 계산할 수 있게 해주는 특별한 함수예요. 윈도우 함수는 *윈도우 사양(window specification)*을 포함하는 OVER 절로 표시돼요. 윈도우 사양은 윈도우 함수가 계산되는 프레임 또는 맥락을 정의해요. 더 자세한 내용은 윈도우 함수 페이지를 참고하세요.

unnest 함수

배열을 한 단계 풀어내요 (unnest):

SELECT unnest([1, 2, 3]);

구조체(struct)를 한 단계 풀어내요:

SELECT unnest({'a': 42, 'b': 84});

unnest 함수는 배열(array), 리스트(list), 또는 구조체(struct)와 함께 사용할 수 있는 특별한 함수예요. unnest 함수는 타입에서 중첩 한 단계를 벗겨내요. 예를 들어 INTEGER[]INTEGER로 변환되고, STRUCT(a INTEGER, b INTEGER)a INTEGER, b INTEGER로 변환돼요. unnest 함수는 중첩 타입을 일반적인 스칼라 타입으로 변환하는 데 사용할 수 있어, 다루기가 더 쉬워져요.

더 알아보기 (Learn more)