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

# SQL 기반 시각화

> ClickStack에서 SQL 쿼리로 시각화 만들기

export const Image = ({img, alt, size = "lg", background}) => {
  const normalizedSize = ["sm", "md", "lg"].includes(size) ? size : "lg";
  const backgroundColor = background === "white" ? "white" : background === "black" ? "rgb(31 31 28)" : undefined;
  return <div className={`ch-image-${normalizedSize}`}>
      <Frame>
        <img src={img} alt={alt} style={{
    backgroundColor
  }} />
      </Frame>
    </div>;
};

ClickStack는 직접 작성한 SQL 쿼리를 기반으로 하는 시각화를 지원합니다. 이를 통해 대시보드 수준의 시간 범위, 필터, 차트 렌더링과 계속 연동하면서도 쿼리 로직을 완전히 제어할 수 있습니다.

SQL 기반 시각화는 기본 제공되는 Chart Explorer만으로는 부족한 작업이 필요할 때 유용합니다. 예를 들어 테이블을 join하거나 차트 빌더에서 지원하지 않는 복잡한 집계를 구성할 때 사용할 수 있습니다.

<div id="creating-a-raw-sql-chart">
  ## SQL 기반 시각화 만들기
</div>

SQL 기반 시각화를 만들려면 대시보드 타일 편집기를 열고 **SQL** 탭을 선택합니다.

<Image img="https://mintcdn.com/private-7c7dfe99-vortex-format/K8mBGehJZkP5k-VE/images/use-cases/observability/sql-editor-button.webp?fit=max&auto=format&n=K8mBGehJZkP5k-VE&q=85&s=04300d78f016713b21205c9e425ae04f" alt="SQL Editor 버튼" size="lg" width="2072" height="599" data-path="images/use-cases/observability/sql-editor-button.webp" />

여기서 다음을 수행합니다:

1. 쿼리를 실행할 **ClickHouse 연결**을 선택합니다.
2. 필요에 따라 **Source**를 선택합니다. 이렇게 하면 `$__filters` 매크로를 통해 대시보드 수준 필터를 차트에 적용할 수 있습니다.
3. 편집기에서 SQL 쿼리를 작성하고, 쿼리 매개변수와 매크로를 사용해 대시보드 시간 범위, 필터 및 변수와 연동합니다.
4. **실행** 버튼을 클릭해 결과를 미리 본 다음 **저장**합니다.

<div id="query-parameters">
  ## 쿼리 매개변수
</div>

[쿼리 매개변수](/ko/reference/syntax#defining-and-using-query-parameters)를 사용하면 SQL에서 대시보드의 현재 시간 범위와 세분화 수준을 참조할 수 있습니다. 쿼리 매개변수는 ClickHouse 매개변수화 쿼리 구문 `{paramName:Type}`을 사용합니다.

<div id="available-parameters">
  ### 사용 가능한 매개변수
</div>

사용 가능한 매개변수는 차트 유형에 따라 달라집니다.

**Line 및 Stacked Bar 차트:**

| 매개변수                            | 유형    | 설명                           |
| ------------------------------- | ----- | ---------------------------- |
| `{startDateMilliseconds:Int64}` | Int64 | 대시보드 날짜 범위의 시작(epoch 기준 밀리초) |
| `{endDateMilliseconds:Int64}`   | Int64 | 대시보드 날짜 범위의 끝(epoch 기준 밀리초)  |
| `{intervalSeconds:Int64}`       | Int64 | 시간 버킷 크기(세분화 수준 기준, 초 단위)    |
| `{intervalMilliseconds:Int64}`  | Int64 | 시간 버킷 크기(세분화 수준 기준, 밀리초 단위)  |

**Table, Pie 및 Number 차트:**

| 매개변수                            | 유형    | 설명                           |
| ------------------------------- | ----- | ---------------------------- |
| `{startDateMilliseconds:Int64}` | Int64 | 대시보드 날짜 범위의 시작(epoch 기준 밀리초) |
| `{endDateMilliseconds:Int64}`   | Int64 | 대시보드 날짜 범위의 끝(epoch 기준 밀리초)  |

<div id="macros">
  ## 매크로
</div>

매크로는 자주 사용하는 ClickHouse SQL 표현식으로 확장되는 단축 구문입니다. `$__` 접두사가 붙으며, 쿼리가 ClickHouse로 전송되기 전에 치환됩니다.

<div id="time-boundary-macros">
  ### 시간 경계 매크로
</div>

이 매크로는 대시보드의 시작 시간 또는 종료 시간을 나타내는 ClickHouse 표현식을 반환합니다. 인수는 없습니다.

| Macro            | Expands to                                                            | Column type |
| ---------------- | --------------------------------------------------------------------- | ----------- |
| `$__fromTime`    | `toDateTime(fromUnixTimestamp64Milli({startDateMilliseconds:Int64}))` | DateTime    |
| `$__toTime`      | `toDateTime(fromUnixTimestamp64Milli({endDateMilliseconds:Int64}))`   | DateTime    |
| `$__fromTime_ms` | `fromUnixTimestamp64Milli({startDateMilliseconds:Int64})`             | DateTime64  |
| `$__toTime_ms`   | `fromUnixTimestamp64Milli({endDateMilliseconds:Int64})`               | DateTime64  |
| `$__interval_s`  | `{intervalSeconds:Int64}`                                             | Int64       |

<div id="time-filter-macros">
  ### 시간 필터 매크로
</div>

이 매크로는 컬럼을 대시보드 시간 범위에 맞게 필터링하는 `WHERE` 절 조각을 생성합니다.

| 매크로                                   | 설명                                          |
| ------------------------------------- | ------------------------------------------- |
| `$__timeFilter(column)`               | `DateTime` 컬럼을 대시보드 시간 범위에 맞게 필터링합니다        |
| `$__timeFilter_ms(column)`            | `DateTime64`(밀리초) 컬럼을 대시보드 시간 범위에 맞게 필터링합니다 |
| `$__dateFilter(column)`               | `Date` 컬럼을 대시보드 시간 범위에 맞게 필터링합니다            |
| `$__dateTimeFilter(dateCol, timeCol)` | 별도의 `Date` 및 `DateTime` 컬럼을 사용하여 필터링합니다     |
| `$__dt(dateCol, timeCol)`             | `$__dateTimeFilter`의 별칭입니다                  |

`$__timeFilter(TimestampTime)`의 **예시 확장**:

```sql theme={null}
TimestampTime >= toDateTime(fromUnixTimestamp64Milli({startDateMilliseconds:Int64}))
AND TimestampTime <= toDateTime(fromUnixTimestamp64Milli({endDateMilliseconds:Int64}))
```

<div id="time-interval-macros">
  ### 시간 인터벌 매크로
</div>

이 매크로는 타임스탬프 컬럼을 대시보드의 세분화 수준에 맞는 인터벌로 묶습니다. 일반적으로 시계열 차트에서 `SELECT` 및 `GROUP BY` 절에 사용됩니다. 이 매크로는 Line 및 Stacked-bar 시각화에서만 사용할 수 있습니다.

| 매크로                          | 설명                                                     |
| ---------------------------- | ------------------------------------------------------ |
| `$__timeInterval(column)`    | `DateTime` 컬럼을 `intervalSeconds` 단위의 인터벌로 묶습니다.        |
| `$__timeInterval_ms(column)` | `DateTime64` 컬럼을 `intervalMilliseconds` 단위의 인터벌로 묶습니다. |

`$__timeInterval(TimestampTime)`의 **확장 예시**:

```sql theme={null}
toStartOfInterval(toDateTime(TimestampTime), INTERVAL {intervalSeconds:Int64} second)
```

<div id="dashboard-filter-macro">
  ### 대시보드 필터 매크로
</div>

| Macro        | Description                                      |
| ------------ | ------------------------------------------------ |
| `$__filters` | 대시보드 수준에서 설정된 필터 조건으로 대체됩니다 (Source가 선택되어 있어야 함) |

차트에서 **Source**가 선택되어 있고 대시보드 필터가 활성화되어 있으면 `$__filters`는 해당 SQL `WHERE` 조건으로 확장됩니다. Source가 선택되지 않았거나 적용된 필터가 없으면 `(1=1)`로 확장되므로 `WHERE` 절에 포함해도 항상 안전합니다.

**Broadcast filter condition**이 활성화된 필터만 `$__filters`에 적용됩니다. 변수로 노출된 필터는 아래에 설명된 대로 명시적으로 참조합니다.

<div id="dashboard-variables">
  ### 대시보드 변수 매크로
</div>

대시보드 필터를 [변수로 사용할 수 있는 경우](/ko/clickstack/features/dashboards/overview#dashboard-variables), 선택된 값을 쿼리 어디에서나 참조할 수 있습니다. 이러한 매크로는 하나 이상의 변수를 선언한 대시보드에 속한 타일에서만 사용할 수 있습니다.

| 매크로                                           | 설명                                                                                              |
| --------------------------------------------- | ----------------------------------------------------------------------------------------------- |
| `$__filter($<variable>)`                      | `variable`에 값이 선택되면 `toString(<filter expression>) IN ($variable)`로 확장되며, 그렇지 않으면 `1=1`로 확장됩니다. |
| `$__filter(<expression>, $<variable>)`        | `variable`에 값이 선택되면 `<expression> IN ($variable)`로 확장되며, 그렇지 않으면 `1=1`로 확장됩니다.                  |
| `$__conditionalAll(<condition>, $<variable>)` | 변수에 선택된 값이 있으면 `<condition>`으로 확장되며, 그렇지 않으면 `1=1`로 확장됩니다.                                      |

변수 값은 `$name` 또는 `${name}`으로 직접 보간할 수도 있으며, 선택적으로 포맷을 지정할 수 있습니다. `${name:sqlstring}`(기본값), `${name:csv}`, `${name:regex}`를 사용할 수 있습니다. 기본 포맷에서 직접 참조하면 아무 값도 선택되지 않은 경우 `NULL`이 렌더링되므로, 프레디케이트가 필요한 곳에서는 위 매크로를 사용하는 것이 좋습니다.

<div id="how-results-are-plotted">
  ## 쿼리 결과가 차트에 표시되는 방법
</div>

ClickStack는 컬럼 타입에 따라 결과 컬럼을 차트 요소에 자동으로 매핑합니다. 매핑 규칙은 차트 유형별로 다릅니다.

<div id="line-and-stacked-bar-charts">
  ### Line 및 Stacked Bar 차트
</div>

| 역할        | 컬럼 유형                        | 설명                                          |
| --------- | ---------------------------- | ------------------------------------------- |
| **타임스탬프** | 첫 번째 `Date` 또는 `DateTime` 컬럼 | x축으로 사용됩니다.                                 |
| **시리즈 값** | 모든 숫자형 컬럼                    | 각 숫자형 컬럼은 각각 별도의 시리즈로 그려집니다. 일반적으로 집계 값입니다. |
| **그룹 이름** | String, 맵 또는 배열 컬럼           | 선택 사항입니다. 그룹 값이 서로 다른 행은 각각 별도의 시리즈로 그려집니다. |

<div id="pie-chart">
  ### 파이 차트
</div>

| 역할         | 컬럼 유형              | 설명                              |
| ---------- | ------------------ | ------------------------------- |
| **조각 값**   | 첫 번째 숫자형 컬럼        | 각 조각의 크기를 결정합니다.                |
| **조각 레이블** | String, 맵 또는 배열 컬럼 | 선택 사항입니다. 고유한 각 값이 조각 레이블이 됩니다. |

<div id="number-chart">
  ### 숫자 차트
</div>

| 역할     | 컬럼 유형      | 설명                           |
| ------ | ---------- | ---------------------------- |
| **숫자** | 첫 번째 숫자 컬럼 | 첫 번째 숫자 컬럼의 첫 번째 행 값이 표시됩니다. |

<div id="table-chart">
  ### 테이블 차트
</div>

모든 결과 컬럼이 테이블의 컬럼으로 직접 표시됩니다.

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

<Info>
  **필수 system table 접근 권한**

  [play-clickstack.clickhouse.com](https://play-clickstack.clickhouse.com)에서 다음 예시를 실행하려면 `otel_v2.otel_logs` 또는 `otel_v2.otel_traces`를 지정해야 합니다.
</Info>

<div id="example-line-chart">
  ### 라인 차트 — 서비스별 시간대별 로그 수
</div>

이 쿼리는 대시보드 세분화 수준에 맞춰 시간 인터벌별로 로그 이벤트 수를 서비스별로 집계합니다.

```sql theme={null}
SELECT
  toStartOfInterval(TimestampTime, INTERVAL {intervalSeconds:Int64} second) AS ts,
  ServiceName,
  count() AS count
FROM otel_logs
WHERE TimestampTime >= fromUnixTimestamp64Milli({startDateMilliseconds:Int64})
  AND TimestampTime < fromUnixTimestamp64Milli({endDateMilliseconds:Int64})
  AND $__filters
GROUP BY ServiceName, ts
ORDER BY ts ASC
```

* `ts` (DateTime)는 x축 타임스탬프로 사용됩니다.
* `count` (numeric)는 시리즈 값으로 표시됩니다.
* `ServiceName` (string)은 서비스마다 별도의 선을 생성합니다.

<div id="example-line-chart-macros">
  ### 라인 차트 — 매크로 사용
</div>

간결하게 표현하기 위해 매크로를 사용해 동일한 쿼리를 작성하면 다음과 같습니다:

```sql theme={null}
SELECT
  $__timeInterval(TimestampTime) AS ts,
  ServiceName,
  count() AS count
FROM otel_logs
WHERE $__timeFilter(TimestampTime)
  AND $__filters
GROUP BY ServiceName, ts
ORDER BY ts ASC
```

<div id="example-line-chart-variables">
  ### 라인 차트 — 대시보드 변수 사용
</div>

`ServiceName`에 대한 `service` 변수와 `SeverityText`에 대한 `severity` 변수가 있는 대시보드에서 이 쿼리는 차트를 현재 선택된 서비스로 제한하고 선택된 심각도는 제외합니다. 두 매크로는 변수에서 아무것도 선택되지 않은 경우 `1=1`로 확장되므로, Viewer가 값을 선택하기 전까지 차트는 필터링 없이 표시됩니다.

```sql theme={null}
SELECT
  $__timeInterval(TimestampTime) AS ts,
  count() AS count
FROM otel_logs
WHERE $__timeFilter(TimestampTime)
  AND $__filter(ServiceName, $service)
  AND $__conditionalAll(SeverityText NOT IN ($severity), $severity)
GROUP BY ts
ORDER BY ts ASC
```

<div id="example-stacked-bar">
  ### Stacked Bar 차트 — 심각도별 오류 건수
</div>

```sql theme={null}
SELECT
  $__timeInterval(TimestampTime) AS ts,
  lower(SeverityText),
  count() AS count
FROM otel_logs
WHERE $__timeFilter(TimestampTime)
  AND lower(SeverityText) IN ('error', 'warn')
  AND $__filters
GROUP BY SeverityText, ts
ORDER BY ts ASC
```

<div id="example-table">
  ### 테이블 차트 — 가장 느린 엔드포인트 상위 10개
</div>

```sql theme={null}
SELECT
  SpanName AS endpoint,
  avg(Duration) / 1000 AS avg_duration_ms,
  count() AS request_count
FROM otel_traces
WHERE $__timeFilter(Timestamp)
  AND $__filters
GROUP BY SpanName
ORDER BY avg_duration_ms DESC
LIMIT 10
```

<div id="example-pie">
  ### 파이 차트 — 서비스별 요청 분포
</div>

```sql theme={null}
SELECT
  ServiceName,
  count() AS request_count
FROM otel_traces
WHERE $__timeFilter(Timestamp)
  AND $__filters
GROUP BY ServiceName
```

* `request_count` (숫자형)은 각 조각의 크기를 결정합니다.
* `ServiceName` (문자열)은 각 조각의 레이블을 지정합니다.

<div id="example-number">
  ### 숫자 차트 — 전체 오류 수
</div>

```sql theme={null}
SELECT
  count() AS total_errors
FROM otel_logs
WHERE $__timeFilter(TimestampTime)
  AND SeverityText = 'error'
  AND $__filters
```

첫 번째 행의 숫자 값 `total_errors`가 표시됩니다.

<div id="notes">
  ## 참고 사항
</div>

* SQL 기반 시각화는 `readonly` 모드가 활성화된 상태로 실행되며, `SELECT` 쿼리만 허용됩니다.
* SQL 기반 시각화에는 SQL 쿼리가 정확히 하나만 포함되어야 하며, 여러 쿼리는 지원되지 않습니다.
* SQL Editor는 쿼리 매개변수와 매크로 모두에 대해 자동 완성 제안을 제공합니다.
* 대시보드 필터를 SQL 기반 시각화에 적용하려면 Source를 선택해야 합니다. 정확하게 필터링되도록 Source는 조회하는 테이블과 일치해야 합니다.
* 대시보드 변수에는 Source가 필요하지 않습니다. 값은 타일 자체의 Source가 아니라 대시보드의 필터 드롭다운에서 가져옵니다.
* 대시보드 변수를 참조하는 SQL 타일의 알림은 대시보드에서 선택한 값이 아니라 모든 변수가 비어 있는 상태에서 평가됩니다.
