표현식 API

표현식 API (Expression API)

Expression 클래스는 표현식의 인스턴스를 나타내요. 쿼리 문자열을 파서에 맡기는 대신, 이 API로 표현식을 직접 동적으로 만들어 더 세밀하게 제어할 수 있답니다.

출처: 문서

본문

Expression 클래스는 표현식의 인스턴스를 나타내요.

왜 Expression API를 써야 할까요? (Why Would I Use the Expression API?)

이 API를 쓰면 표현식을 동적으로 만들어 낼 수 있어요. 표현식은 보통 파서가 쿼리 문자열로부터 만드는데, 이 API를 쓰면 그 단계를 건너뛰고 사용하는 표현식을 더 세밀하게 제어할 수 있어요.

아래는 현재 이 API로 만들 수 있는 지원 표현식 목록이에요.

컬럼 표현식 (Column Expression)

이 표현식은 이름으로 컬럼을 참조해요.

import duckdb
import pandas as pd

df = pd.DataFrame({
    'a': [1, 2, 3, 4],
    'b': [True, None, False, True],
    'c': [42, 21, 13, 14]
})

단일 컬럼 선택:

col = duckdb.ColumnExpression('a')
duckdb.df(df).select(col).show()
┌───────┐
│   a   │
│ int64 │
├───────┤
│     1 │
│     2 │
│     3 │
│     4 │
└───────┘

여러 컬럼 선택:

col_list = [
        duckdb.ColumnExpression('a') * 10,
        duckdb.ColumnExpression('b').isnull(),
        duckdb.ColumnExpression('c') + 5
    ]
duckdb.df(df).select(*col_list).show()
┌──────────┬─────────────┬─────────┐
│ (a * 10) │ (b IS NULL) │ (c + 5) │
│  int64   │   boolean   │  int64  │
├──────────┼─────────────┼─────────┤
│       10 │ false       │      47 │
│       20 │ true        │      26 │
│       30 │ false       │      18 │
│       40 │ false       │      19 │
└──────────┴─────────────┴─────────┘

스타 표현식 (Star Expression)

이 표현식은 입력 소스의 모든 컬럼을 선택해요.

선택적으로 exclude 목록을 제공해 테이블의 컬럼을 걸러낼 수 있어요. 이 exclude 목록은 문자열이나 Expression을 담을 수 있어요.

import duckdb
import pandas as pd

df = pd.DataFrame({
    'a': [1, 2, 3, 4],
    'b': [True, None, False, True],
    'c': [42, 21, 13, 14]
})

star = duckdb.StarExpression(exclude = ['b'])
duckdb.df(df).select(star).show()
┌───────┬───────┐
│   a   │   c   │
│ int64 │ int64 │
├───────┼───────┤
│     1 │    42 │
│     2 │    21 │
│     3 │    13 │
│     4 │    14 │
└───────┴───────┘

상수 표현식 (Constant Expression)

이 표현식은 단일 값을 담아요.

import duckdb
import pandas as pd

df = pd.DataFrame({
    'a': [1, 2, 3, 4],
    'b': [True, None, False, True],
    'c': [42, 21, 13, 14]
})

const = duckdb.ConstantExpression('hello')
duckdb.df(df).select(const).show()
┌─────────┐
│ 'hello' │
│ varchar │
├─────────┤
│ hello   │
│ hello   │
│ hello   │
│ hello   │
└─────────┘

CASE 표현식 (Case Expression)

이 표현식은 CASE WHEN (...) THEN (...) ELSE (...) END 표현식을 담아요. 기본적으로 ELSENULL이고, .else(value = ...)로 설정할 수 있어요. 추가 WHEN (...) THEN (...) 블록은 .when(condition = ..., value = ...)로 추가할 수 있어요.

import duckdb
import pandas as pd
from duckdb import (
    ConstantExpression,
    ColumnExpression,
    CaseExpression
)

df = pd.DataFrame({
    'a': [1, 2, 3, 4],
    'b': [True, None, False, True],
    'c': [42, 21, 13, 14]
})

hello = ConstantExpression('hello')
world = ConstantExpression('world')

case = \
    CaseExpression(condition = ColumnExpression('b') == False, value = world) \
    .otherwise(hello)
duckdb.df(df).select(case).show()
┌──────────────────────────────────────────────────────────┐
│ CASE  WHEN ((b = false)) THEN ('world') ELSE 'hello' END │
│                         varchar                          │
├──────────────────────────────────────────────────────────┤
│ hello                                                    │
│ hello                                                    │
│ world                                                    │
│ hello                                                    │
└──────────────────────────────────────────────────────────┘

함수 표현식 (Function Expression)

이 표현식은 함수 호출을 담아요. 함수 이름과 임의 개수의 Expression을 인자로 제공해서 만들 수 있어요.

import duckdb
import pandas as pd
from duckdb import (
    ConstantExpression,
    ColumnExpression,
    FunctionExpression
)

df = pd.DataFrame({
    'a': [1, 2, 3, 4],
    'b': [True, None, False, True],
    'c': [42, 21, 13, 14]
})

multiply_by_2 = FunctionExpression('multiply', ColumnExpression('a'), ConstantExpression(2))
duckdb.df(df).select(multiply_by_2).show()
┌────────────────┐
│ multiply(a, 2) │
│     int64      │
├────────────────┤
│              2 │
│              4 │
│              6 │
│              8 │
└────────────────┘

SQL 표현식 (SQL Expression)

이 표현식은 유효한 SQL 표현식을 담아요.

import duckdb
import pandas as pd

from duckdb import SQLExpression

df = pd.DataFrame({
    'a': [1, 2, 3, 4],
    'b': [True, None, False, True],
    'c': [42, 21, 13, 14]
})

duckdb.df(df).filter(
    SQLExpression("b is true")
).select(
    SQLExpression("a").alias("selecting_column_a"),
    SQLExpression("case when a = 1 then 1 else 0 end").alias("selecting_case_expression"),
    SQLExpression("1").alias("constant_numeric_column"),
    SQLExpression("'hello'").alias("constant_text_column")
).aggregate(
    aggr_expr=[
        SQLExpression("SUM(selecting_column_a)").alias("sum_a"), 
        "selecting_case_expression" , 
        "constant_numeric_column", 
        "constant_text_column"
    ],
).show()
┌────────┬───────────────────────────┬─────────────────────────┬──────────────────────┐
│ sum_a  │ selecting_case_expression │ constant_numeric_column │ constant_text_column │
│ int128 │           int32           │          int32          │       varchar        │
├────────┼───────────────────────────┼─────────────────────────┼──────────────────────┤
│      4 │                         0 │                       1 │ hello                │
│      1 │                         1 │                       1 │ hello                │
└────────┴───────────────────────────┴─────────────────────────┴──────────────────────┘

공통 연산 (Common Operations)

Expression 클래스는 어떤 Expression 타입에도 적용할 수 있는 많은 연산도 담고 있어요.

연산 설명
.alias(name: str) 표현식에 별칭을 적용해요
.cast(type: DuckDBPyType) 표현식에 주어진 타입으로 캐스트를 적용해요
.isin(*exprs: Expression) 주어진 표현식들을 목록으로 하는 IN 표현식을 만들어요
.isnotin(*exprs: Expression) 주어진 표현식들을 목록으로 하는 NOT IN 표현식을 만들어요
.isnotnull() 표현식이 NULL이 아닌지 확인해요
.isnull() 표현식이 NULL인지 확인해요

정렬 연산 (Order Operations)

표현식이 DuckDBPyRelation.order()에 제공될 때 다음 정렬 연산을 적용할 수 있어요.

연산 설명
.asc() 이 표현식이 오름차순으로 정렬되어야 함을 나타내요
.desc() 이 표현식이 내림차순으로 정렬되어야 함을 나타내요
.nulls_first() 이 표현식의 null이 non-null 값보다 앞에 와야 함을 나타내요
.nulls_last() 이 표현식의 null이 non-null 값 뒤에 와야 함을 나타내요

더 알아보기 (Learn more)