메인 콘텐츠로 건너뛰기
LIMIT n BY expressions 절이 있는 쿼리는 expressions의 각 고유 값마다 처음 n개의 행을 선택합니다. LIMIT BY의 키에는 개수 제한 없이 expressions을 얼마든지 포함할 수 있습니다. ClickHouse는 다음 구문 변형을 지원합니다.
  • LIMIT [offset_value, ]n BY expressions
  • LIMIT n OFFSET offset_value BY expressions
쿼리 처리 중 ClickHouse는 정렬 키(sorting key) 순으로 정렬된 데이터를 선택합니다. 정렬 키는 ORDER BY 절로 명시적으로 설정하거나 테이블 엔진의 속성으로 암묵적으로 설정할 수 있습니다(ORDER BY를 사용할 때만 행 순서가 보장되며, 그렇지 않으면 멀티스레딩으로 인해 행 블록이 정렬되지 않습니다). 그런 다음 ClickHouse는 LIMIT n BY expressions를 적용하여 expressions의 각 고유 조합마다 처음 n개의 행을 반환합니다. OFFSET이 지정된 경우, ClickHouse는 expressions의 고유 조합에 속하는 각 데이터 블록에서 블록 시작 부분의 offset_value개 행을 건너뛰고 최대 n개의 행을 결과로 반환합니다. offset_value가 데이터 블록의 행 수보다 크면 ClickHouse는 해당 블록에서 행을 반환하지 않습니다.
LIMIT BYLIMIT와 관련이 없습니다. 두 절은 같은 쿼리에서 함께 사용할 수 있습니다.
LIMIT BY 절에서 컬럼 이름 대신 컬럼 번호를 사용하려면 enable_positional_arguments 설정을 활성화하세요.

예시

샘플 테이블:
CREATE TABLE limit_by(id Int, val Int) ENGINE = Memory;
INSERT INTO limit_by VALUES (1, 10), (1, 11), (1, 12), (2, 20), (2, 21);
쿼리:
SELECT * FROM limit_by ORDER BY id, val LIMIT 2 BY id;
┌─id─┬─val─┐
│  1 │  10 │
│  1 │  11 │
│  2 │  20 │
│  2 │  21 │
└────┴─────┘
SELECT * FROM limit_by ORDER BY id, val LIMIT 1, 2 BY id;
┌─id─┬─val─┐
│  1 │  11 │
│  1 │  12 │
│  2 │  21 │
└────┴─────┘
SELECT * FROM limit_by ORDER BY id, val LIMIT 2 OFFSET 1 BY id 쿼리는 같은 결과를 반환합니다. 다음 쿼리는 각 domain, device_type 쌍별로 상위 5개의 리퍼러를 반환하며, 전체 행 수는 최대 100개로 제한됩니다(LIMIT n BY + LIMIT).
SELECT
    domainWithoutWWW(URL) AS domain,
    domainWithoutWWW(REFERRER_URL) AS referrer,
    device_type,
    count() cnt
FROM hits
GROUP BY domain, referrer, device_type
ORDER BY cnt DESC
LIMIT 5 BY domain, device_type
LIMIT 100;
LIMIT BY는 음수 limit 및 offset에서도 작동합니다. 음수 LIMIT 절과 마찬가지로 LIMIT BY에서도 음수 값을 사용해 각 그룹의 에서부터 행을 선택할 수 있습니다.
SELECT * FROM limit_by ORDER BY id, val LIMIT -2 BY id;
┌─id─┬─val─┐
│  1 │  11 │
│  1 │  12 │
│  2 │  20 │
│  2 │  21 │
└────┴─────┘
id에 대해 마지막 2개 행을 반환합니다. id = 1이면 11번과 12번 행이 반환되고, id = 2는 그룹에 행이 2개뿐이므로 두 행이 모두 반환됩니다.
SELECT * FROM limit_by ORDER BY id, val LIMIT -1 OFFSET -1 BY id;
┌─id─┬─val─┐
│  1 │  11 │
│  2 │  20 │
└────┴─────┘
id의 끝에서 두 번째 행을 반환합니다. 뒤의 OFFSET -1은 각 그룹의 마지막 행을 제외하고, 앞의 -1은 남은 행들 중 마지막 행만 유지합니다. 부호가 다른 LIMITOFFSET도 함께 사용할 수 있습니다. 예를 들어, 각 그룹의 첫 번째 행을 제외한 뒤 남은 행들 중 마지막 2개를 유지하려면 다음과 같습니다:
SELECT * FROM limit_by ORDER BY id, val LIMIT -2 OFFSET 1 BY id;
┌─id─┬─val─┐
│  1 │  11 │
│  1 │  12 │
│  2 │  21 │
└────┴─────┘
id = 1에서는 첫 번째 행(10)이 건너뛰어지고, 11, 12 중 마지막 2개가 모두 반환됩니다. id = 2에서는 첫 번째 행(20)이 건너뛰어져 21만 남습니다.

LIMIT BY ALL

LIMIT BY ALL은 집계 함수가 아닌 모든 SELECT 표현식을 나열하는 것과 동일합니다. 예시:
SELECT col1, col2, col3 FROM table LIMIT 2 BY ALL;
와 같습니다
SELECT col1, col2, col3 FROM table LIMIT 2 BY col1, col2, col3;
특수한 경우로, 어떤 함수의 인수에 집계 함수와 다른 필드가 함께 포함되어 있으면 LIMIT BY 키에는 그 함수에서 추출할 수 있는 비집계 필드가 최대한 포함됩니다. 예를 들어:
SELECT substring(a, 4, 2), substring(substring(a, 1, 2), 1, count(b)) FROM t LIMIT 2 BY ALL;
와 같습니다
SELECT substring(a, 4, 2), substring(substring(a, 1, 2), 1, count(b)) FROM t LIMIT 2 BY substring(a, 4, 2), substring(a, 1, 2);

예시

샘플 테이블:
CREATE TABLE limit_by(id Int, val Int) ENGINE = Memory;
INSERT INTO limit_by VALUES (1, 10), (1, 11), (1, 12), (2, 20), (2, 21);
쿼리:
SELECT * FROM limit_by ORDER BY id, val LIMIT 2 BY id;
┌─id─┬─val─┐
│  1 │  10 │
│  1 │  11 │
│  2 │  20 │
│  2 │  21 │
└────┴─────┘
SELECT * FROM limit_by ORDER BY id, val LIMIT 1, 2 BY id;
┌─id─┬─val─┐
│  1 │  11 │
│  1 │  12 │
│  2 │  21 │
└────┴─────┘
SELECT * FROM limit_by ORDER BY id, val LIMIT 2 OFFSET 1 BY id 쿼리도 동일한 결과를 반환합니다. LIMIT BY ALL 사용:
SELECT id, val FROM limit_by ORDER BY id, val LIMIT 2 BY ALL;
이는 다음과 같습니다:
SELECT id, val FROM limit_by ORDER BY id, val LIMIT 2 BY id, val;
마지막 수정일 2026년 6월 10일