SQL 연산 수행하기

SQL 연산 수행하기 (Perform SQL operations)

DuckDB로 SQL 연산을 수행하면 데이터셋을 효율적으로 쿼리할 수 있는 세계가 열려요. DuckDB 함수의 강력함을 보여주는 예시를 함께 살펴보겠습니다.

출처: 문서

본문

DuckDB로 SQL 연산을 수행하면 데이터셋을 효율적으로 쿼리할 수 있는 무궁무진한 가능성이 열립니다. DuckDB 함수의 강력함을 보여주는 몇 가지 예시를 살펴봐요.

데모를 위해 흥미로운 데이터셋을 탐색해 보겠습니다. MMLU 데이터셋은 다양한 지식 영역에 걸친 객관식 질문을 담은 멀티태스크 테스트입니다.

데이터셋을 미리 보려면 3개 행의 샘플을 선택해 봅시다:

FROM 'hf://datasets/cais/mmlu/all/test-*.parquet' USING SAMPLE 3;

┌──────────────────────┬──────────────────────┬──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┬────────┐
│       question       │       subject        │                                                                         choices                                                                          │ answer │
│       varchar        │       varchar        │                                                                        varchar[]                                                                         │ int64  │
├──────────────────────┼──────────────────────┼────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┼────────┤
│ The model of light…  │ conceptual_physics   │ [wave model, particle model, Both of these, Neither of these]                                                                                            │      1 │
│ A person who is lo…  │ professional_psych…  │ [his/her life scripts., his/her own feelings, attitudes, and beliefs., the emotional reactions and behaviors of the people he/she is interacting with.…  │      1 │
│ The thermic effect…  │ nutrition            │ [is substantially higher for carbohydrate than for protein, is accompanied by a slight decrease in body core temperature., is partly related to sympat…  │      2 │
└──────────────────────┴──────────────────────┴────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┴────────┘

이 명령은 데이터셋에서 무작위 3개 행 샘플을 가져와 살펴볼 수 있게 해줍니다.

먼저 데이터셋의 스키마를 확인해 봅시다. 다음 테이블은 데이터셋의 구조를 보여줍니다:

DESCRIBE FROM 'hf://datasets/cais/mmlu/all/test-*.parquet' USING SAMPLE 3;
┌─────────────┬─────────────┬─────────┬─────────┬─────────┬─────────┐
│ column_name │ column_type │  null   │   key   │ default │  extra  │
│   varchar   │   varchar   │ varchar │ varchar │ varchar │ varchar │
├─────────────┼─────────────┼─────────┼─────────┼─────────┼─────────┤
│ question    │ VARCHAR     │ YES     │         │         │         │
│ subject     │ VARCHAR     │ YES     │         │         │         │
│ choices     │ VARCHAR[]   │ YES     │         │         │         │
│ answer      │ BIGINT      │ YES     │         │         │         │
└─────────────┴─────────────┴─────────┴─────────┴─────────┴─────────┘

다음으로 데이터셋에 중복 레코드가 있는지 분석해 봅시다:

SELECT   *,
         COUNT(*) AS counts
FROM     'hf://datasets/cais/mmlu/all/test-*.parquet'
GROUP BY ALL
HAVING   counts > 2;

┌──────────┬─────────┬───────────┬────────┬────────┐
│ question │ subject │  choices  │ answer │ counts │
│ varchar  │ varchar │ varchar[] │ int64  │ int64  │
├──────────┴─────────┴───────────┴────────┴────────┤
│                      0 rows                      │
└──────────────────────────────────────────────────┘

다행히 우리 데이터셋에는 중복 레코드가 없어요.

주제별 질문 비율을 막대(bar) 표현으로 확인해 봅시다:

SELECT 
    subject, 
    COUNT(*) AS counts, 
    BAR(COUNT(*), 0, (SELECT COUNT(*) FROM 'hf://datasets/cais/mmlu/all/test-*.parquet')) AS percentage 
FROM 
    'hf://datasets/cais/mmlu/all/test-*.parquet' 
GROUP BY 
    subject 
ORDER BY 
    counts DESC;

┌──────────────────────────────┬────────┬────────────────────────────────────────────────────────────────────────────────┐
│           subject            │ counts │                                   percentage                                   │
│           varchar            │ int64  │                                    varchar                                     │
├──────────────────────────────┼────────┼────────────────────────────────────────────────────────────────────────────────┤
│ professional_law             │   1534 │ ████████▋                                                                      │
│ moral_scenarios              │    895 │ █████                                                                          │
│ miscellaneous                │    783 │ ████▍                                                                          │
│ professional_psychology      │    612 │ ███▍                                                                           │
│ high_school_psychology       │    545 │ ███                                                                            │
│ high_school_macroeconomics   │    390 │ ██▏                                                                            │
│ elementary_mathematics       │    378 │ ██▏                                                                            │
│ moral_disputes               │    346 │ █▉                                                                             │
├──────────────────────────────┴────────┴────────────────────────────────────────────────────────────────────────────────┤
│ 57 rows (8 shown)                                                                                           3 columns  │
└────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘

이제 nutrition(영양) 관련 질문이 담긴 데이터셋 하위 집합을 준비하고 질문과 정답의 매핑을 만들어 봅시다. choices 컬럼이 있고, answer 컬럼을 인덱스로 사용해 정답을 얻을 수 있다는 점을 확인하세요.

SELECT *
FROM   'hf://datasets/cais/mmlu/all/test-*.parquet'
WHERE  subject = 'nutrition' LIMIT 3;

┌──────────────────────┬───────────┬─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┬────────┐
│       question       │  subject  │                                                                               choices                                                                               │ answer │
│       varchar        │  varchar  │                                                                              varchar[]                                                                              │ int64  │
├──────────────────────┼───────────┼─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┼────────┤
│ Which foods tend t…  │ nutrition │ [Meat, Confectionary, Fruits and vegetables, Potatoes]                                                                                                              │      2 │
│ In which one of th…  │ nutrition │ [If the incidence rate of the disease falls., If survival time with the disease increases., If recovery of the disease is faster., If the population in which the…  │      1 │
│ Which of the follo…  │ nutrition │ [The flavonoid class comprises flavonoids and isoflavonoids., The digestibility and bioavailability of isoflavones in soya food products are not changed by proce…  │      0 │
└──────────────────────┴───────────┴─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┴────────┘

SELECT question,
       choices[answer] AS correct_answer
FROM   'hf://datasets/cais/mmlu/all/test-*.parquet'
WHERE  subject = 'nutrition' LIMIT 3;

┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┬─────────────────────────────────────────────┐
│                                                              question                                                               │               correct_answer                │
│                                                               varchar                                                               │                   varchar                   │
├─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┼─────────────────────────────────────────────┤
│ Which foods tend to be consumed in lower quantities in Wales and Scotland (as of 2020)?\n                                           │ Confectionary                               │
│ In which one of the following circumstances will the prevalence of a disease in the population increase, all else being constant?\n │ If the incidence rate of the disease falls. │
│ Which of the following statements is correct?\n                                                                                     │                                             │
└─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┴─────────────────────────────────────────────┘

데이터 정결성을 위해 질문 끝의 개행 문자를 제거하고 빈 답변을 걸러봅시다:

SELECT regexp_replace(question, '\n', '') AS question,
       choices[answer] AS correct_answer
FROM   'hf://datasets/cais/mmlu/all/test-*.parquet'
WHERE  subject = 'nutrition' AND LENGTH(correct_answer) > 0 LIMIT 3;

┌───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┬─────────────────────────────────────────────┐
│                                                             question                                                              │               correct_answer                │
│                                                              varchar                                                              │                   varchar                   │
├───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┼─────────────────────────────────────────────┤
│ Which foods tend to be consumed in lower quantities in Wales and Scotland (as of 2020)?                                           │ Confectionary                               │
│ In which one of the following circumstances will the prevalence of a disease in the population increase, all else being constant? │ If the incidence rate of the disease falls. │
│ Which vitamin is a major lipid-soluble antioxidant in cell membranes?                                                             │ Vitamin D                                   │
└───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┴─────────────────────────────────────────────┘

마지막으로 이 섹션에서 사용한 DuckDB 함수 일부를 정리하면:

  • DESCRIBE, 테이블 스키마를 반환합니다.
  • USING SAMPLE, 데이터셋의 하위 집합을 무작위로 선택하는 샘플링에 사용됩니다.
  • BAR, (x - min)에 비례하는 너비의 막대를 그리고, x = max일 때 width 문자와 같습니다. width 기본값은 80입니다.
  • string[begin:end], 슬라이스 표기로 문자열을 추출합니다. begin 또는 end 인자가 없으면 각각 리스트의 시작 또는 끝으로 해석되고, 음수 값도 허용됩니다.
  • regexp_replace, 문자열에 regexp 패턴이 있으면 일치 부분을 replacement로 바꿉니다.
  • LENGTH, 문자열의 문자 수를 가져옵니다.

[!TIP] DuckDB의 SQL 함수 개요에는 유용한 함수가 아주 많아요. 가장 좋은 점은 이 함수들을 Hugging Face 데이터셋에 직접 사용할 수 있다는 것입니다.

더 알아보기 (Learn more)

DuckDB로 hf://datasets/<repo>/... 경로를 SQL에서 직접 읽으면 별도 다운로드 없이 데이터셋을 쿼리할 수 있어요. USING SAMPLE, BAR, regexp_replace, LENGTH 같은 함수를 조합해 데이터 탐색·전처리 파이프라인을 만들어 보세요. DuckDB의 SQL 함수 목록과 스트리밍 문서(datasets-streaming)를 함께 참고하면 좋습니다.