> ## Documentation Index
> Fetch the complete documentation index at: https://private-7c7dfe99-fix-nav-issues.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

> LIMIT BY 절 문서

# LIMIT BY 절

`LIMIT n BY expressions` 절이 있는 쿼리는 `expressions`의 각 고유 값마다 처음 `n`개의 행을 선택합니다. `LIMIT BY`의 키에는 개수 제한 없이 [expressions](/ko/reference/syntax#expressions)을 얼마든지 포함할 수 있습니다.

ClickHouse는 다음 구문 변형을 지원합니다.

* `LIMIT [offset_value, ]n BY expressions`
* `LIMIT n OFFSET offset_value BY expressions`

쿼리 처리 중 ClickHouse는 정렬 키(sorting key) 순으로 정렬된 데이터를 선택합니다. 정렬 키는 [ORDER BY](/ko/reference/statements/select/order-by) 절로 명시적으로 설정하거나 테이블 엔진의 속성으로 암묵적으로 설정할 수 있습니다([ORDER BY](/ko/reference/statements/select/order-by)를 사용할 때만 행 순서가 보장되며, 그렇지 않으면 멀티스레딩으로 인해 행 블록이 정렬되지 않습니다). 그런 다음 ClickHouse는 `LIMIT n BY expressions`를 적용하여 `expressions`의 각 고유 조합마다 처음 `n`개의 행을 반환합니다. `OFFSET`이 지정된 경우, ClickHouse는 `expressions`의 고유 조합에 속하는 각 데이터 블록에서 블록 시작 부분의 `offset_value`개 행을 건너뛰고 최대 `n`개의 행을 결과로 반환합니다. `offset_value`가 데이터 블록의 행 수보다 크면 ClickHouse는 해당 블록에서 행을 반환하지 않습니다.

<Note>
  `LIMIT BY`는 [LIMIT](/ko/reference/statements/select/limit)와 관련이 없습니다. 두 절은 같은 쿼리에서 함께 사용할 수 있습니다.
</Note>

`LIMIT BY` 절에서 컬럼 이름 대신 컬럼 번호를 사용하려면 [enable\_positional\_arguments](/ko/reference/settings/session-settings#enable_positional_arguments) 설정을 활성화하세요.

<div id="examples">
  ## 예시
</div>

샘플 테이블:

```sql theme={null}
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);
```

쿼리:

```sql theme={null}
SELECT * FROM limit_by ORDER BY id, val LIMIT 2 BY id;
```

```text theme={null}
┌─id─┬─val─┐
│  1 │  10 │
│  1 │  11 │
│  2 │  20 │
│  2 │  21 │
└────┴─────┘
```

```sql theme={null}
SELECT * FROM limit_by ORDER BY id, val LIMIT 1, 2 BY id;
```

```text theme={null}
┌─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`).

```sql theme={null}
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 절](/ko/reference/statements/select/limit#negative-limits)과 마찬가지로 `LIMIT BY`에서도 음수 값을 사용해 각 그룹의 *끝*에서부터 행을 선택할 수 있습니다.

```sql theme={null}
SELECT * FROM limit_by ORDER BY id, val LIMIT -2 BY id;
```

```text theme={null}
┌─id─┬─val─┐
│  1 │  11 │
│  1 │  12 │
│  2 │  20 │
│  2 │  21 │
└────┴─────┘
```

각 `id`에 대해 마지막 2개 행을 반환합니다. `id = 1`이면 `11`번과 `12`번 행이 반환되고, `id = 2`는 그룹에 행이 2개뿐이므로 두 행이 모두 반환됩니다.

```sql theme={null}
SELECT * FROM limit_by ORDER BY id, val LIMIT -1 OFFSET -1 BY id;
```

```text theme={null}
┌─id─┬─val─┐
│  1 │  11 │
│  2 │  20 │
└────┴─────┘
```

각 `id`의 끝에서 두 번째 행을 반환합니다. 뒤의 `OFFSET -1`은 각 그룹의 마지막 행을 제외하고, 앞의 `-1`은 남은 행들 중 마지막 행만 유지합니다.

부호가 다른 `LIMIT`과 `OFFSET`도 함께 사용할 수 있습니다. 예를 들어, 각 그룹의 첫 번째 행을 제외한 뒤 남은 행들 중 마지막 2개를 유지하려면 다음과 같습니다:

```sql theme={null}
SELECT * FROM limit_by ORDER BY id, val LIMIT -2 OFFSET 1 BY id;
```

```text theme={null}
┌─id─┬─val─┐
│  1 │  11 │
│  1 │  12 │
│  2 │  21 │
└────┴─────┘
```

`id = 1`에서는 첫 번째 행(`10`)이 건너뛰어지고, `11, 12` 중 마지막 2개가 모두 반환됩니다. `id = 2`에서는 첫 번째 행(`20`)이 건너뛰어져 `21`만 남습니다.

<div id="limit-by-all">
  ## LIMIT BY ALL
</div>

`LIMIT BY ALL`은 집계 함수가 아닌 모든 SELECT 표현식을 나열하는 것과 동일합니다.

예시:

```sql theme={null}
SELECT col1, col2, col3 FROM table LIMIT 2 BY ALL;
```

와 같습니다

```sql theme={null}
SELECT col1, col2, col3 FROM table LIMIT 2 BY col1, col2, col3;
```

특수한 경우로, 어떤 함수의 인수에 집계 함수와 다른 필드가 함께 포함되어 있으면 `LIMIT BY` 키에는 그 함수에서 추출할 수 있는 비집계 필드가 최대한 포함됩니다.

예를 들어:

```sql theme={null}
SELECT substring(a, 4, 2), substring(substring(a, 1, 2), 1, count(b)) FROM t LIMIT 2 BY ALL;
```

와 같습니다

```sql theme={null}
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);
```

<div id="examples">
  ## 예시
</div>

샘플 테이블:

```sql theme={null}
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);
```

쿼리:

```sql theme={null}
SELECT * FROM limit_by ORDER BY id, val LIMIT 2 BY id;
```

```text theme={null}
┌─id─┬─val─┐
│  1 │  10 │
│  1 │  11 │
│  2 │  20 │
│  2 │  21 │
└────┴─────┘
```

```sql theme={null}
SELECT * FROM limit_by ORDER BY id, val LIMIT 1, 2 BY id;
```

```text theme={null}
┌─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` 사용:

```sql theme={null}
SELECT id, val FROM limit_by ORDER BY id, val LIMIT 2 BY ALL;
```

이는 다음과 같습니다:

```sql theme={null}
SELECT id, val FROM limit_by ORDER BY id, val LIMIT 2 BY id, val;
```
