Relational API

Relational API#

  • インクリメンタルにクエリを構築

  • DuckDBPyRelation ノードから呼び出す

  • SQLクエリをシンボリックに表現

  • 実行のトリガーとなるメソッドが呼び出されるまで、リレーションはデータを保持・実行しない

Relationの作成#

  • sql

  • from_arrow

  • from_df

  • read_csv

  • read_json

  • read_parquet

import duckdb

cpi = duckdb.sql(
    "SELECT * FROM 'https://pub-5c988f48e21d45ec95c1e3eca8ab1787.r2.dev/0003427113.parquet'"
)
cpi.show()
┌──────────┬──────────────────────────┬────────────┬───────────────────────────────────────────┬───────────┬────────────────────┬────────────┬──────────────────┬─────────┬────────┬────────────┐
│ tab_code │         表章項目         │ cat01_code │              2020年基準品目               │ area_code │ 地域(2020年基準) │ time_code  │ 時間軸(年・月) │  unit   │ value  │ annotation │
│  int64   │         varchar          │   int64    │                  varchar                  │  varchar  │      varchar       │   int64    │     varchar      │ varchar │ double │   double   │
├──────────┼──────────────────────────┼────────────┼───────────────────────────────────────────┼───────────┼────────────────────┼────────────┼──────────────────┼─────────┼────────┼────────────┤
│        1 │ 指数                     │          1 │ 0001 総合                                 │ 13A01     │ 13100 東京都区部   │ 1970000303 │ 1970年3月        │ NULL    │   31.2 │       NULL │
│        1 │ 指数                     │          1 │ 0001 総合                                 │ 00000     │ 全国               │ 1970000303 │ 1970年3月        │ NULL    │   30.6 │       NULL │
│        1 │ 指数                     │          1 │ 0001 総合                                 │ 00012     │ 大都市             │ 1970000303 │ 1970年3月        │ NULL    │   30.8 │       NULL │
│        1 │ 指数                     │          1 │ 0001 総合                                 │ 00013     │ 中都市             │ 1970000303 │ 1970年3月        │ NULL    │   30.9 │       NULL │
│        1 │ 指数                     │          1 │ 0001 総合                                 │ 00018     │ 小都市A           │ 1970000303 │ 1970年3月        │ NULL    │   30.3 │       NULL │
│        1 │ 指数                     │          1 │ 0001 総合                                 │ 00042     │ 北海道地方         │ 1970000303 │ 1970年3月        │ NULL    │   32.0 │       NULL │
│        1 │ 指数                     │          1 │ 0001 総合                                 │ 00043     │ 東北地方           │ 1970000303 │ 1970年3月        │ NULL    │   30.0 │       NULL │
│        1 │ 指数                     │          1 │ 0001 総合                                 │ 00044     │ 関東地方           │ 1970000303 │ 1970年3月        │ NULL    │   30.7 │       NULL │
│        1 │ 指数                     │          1 │ 0001 総合                                 │ 00049     │ 北陸地方           │ 1970000303 │ 1970年3月        │ NULL    │   30.5 │       NULL │
│        1 │ 指数                     │          1 │ 0001 総合                                 │ 00050     │ 東海地方           │ 1970000303 │ 1970年3月        │ NULL    │   30.7 │       NULL │
│        · │  ·                       │          · │     ·                                     │   ·       │    ·               │      ·     │     ·            │ ·       │     ·  │         ·  │
│        · │  ·                       │          · │     ·                                     │   ·       │    ·               │      ·     │     ·            │ ·       │     ·  │         ·  │
│        · │  ·                       │          · │     ·                                     │   ·       │    ·               │      ·     │     ·            │ ·       │     ·  │         ·  │
│        2 │ 前月比・前年比・前年度比 │        166 │ 0166 持家の帰属家賃及び生鮮食品を除く総合 │ 02A01     │ 02201 青森市       │ 1970000303 │ 1970年3月        │ %       │    0.5 │       NULL │
│        2 │ 前月比・前年比・前年度比 │        166 │ 0166 持家の帰属家賃及び生鮮食品を除く総合 │ 03A01     │ 03201 盛岡市       │ 1970000303 │ 1970年3月        │ %       │    0.3 │       NULL │
│        2 │ 前月比・前年比・前年度比 │        166 │ 0166 持家の帰属家賃及び生鮮食品を除く総合 │ 04A01     │ 04100 仙台市       │ 1970000303 │ 1970年3月        │ %       │    0.4 │       NULL │
│        2 │ 前月比・前年比・前年度比 │        166 │ 0166 持家の帰属家賃及び生鮮食品を除く総合 │ 05A01     │ 05201 秋田市       │ 1970000303 │ 1970年3月        │ %       │    0.0 │       NULL │
│        2 │ 前月比・前年比・前年度比 │        166 │ 0166 持家の帰属家賃及び生鮮食品を除く総合 │ 06A01     │ 06201 山形市       │ 1970000303 │ 1970年3月        │ %       │    0.5 │       NULL │
│        2 │ 前月比・前年比・前年度比 │        166 │ 0166 持家の帰属家賃及び生鮮食品を除く総合 │ 07A01     │ 07201 福島市       │ 1970000303 │ 1970年3月        │ %       │    0.4 │       NULL │
│        2 │ 前月比・前年比・前年度比 │        166 │ 0166 持家の帰属家賃及び生鮮食品を除く総合 │ 08A01     │ 08201 水戸市       │ 1970000303 │ 1970年3月        │ %       │   -0.1 │       NULL │
│        2 │ 前月比・前年比・前年度比 │        166 │ 0166 持家の帰属家賃及び生鮮食品を除く総合 │ 09A01     │ 09201 宇都宮市     │ 1970000303 │ 1970年3月        │ %       │    0.2 │       NULL │
│        2 │ 前月比・前年比・前年度比 │        166 │ 0166 持家の帰属家賃及び生鮮食品を除く総合 │ 10A01     │ 10201 前橋市       │ 1970000303 │ 1970年3月        │ %       │   -0.1 │       NULL │
│        2 │ 前月比・前年比・前年度比 │        166 │ 0166 持家の帰属家賃及び生鮮食品を除く総合 │ 11A01     │ 11100 さいたま市   │ 1970000303 │ 1970年3月        │ %       │    0.0 │       NULL │
├──────────┴──────────────────────────┴────────────┴───────────────────────────────────────────┴───────────┴────────────────────┴────────────┴──────────────────┴─────────┴────────┴────────────┤
│ ? rows (>9999 rows, 20 shown)                                                                                                                                                      11 columns │
└───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘

Note

  • 13009354のデータを計算するRelationsが即座に構築されている

  • サマリの表示( show() )が即座に出力される

Relationは FROM 句から参照できる

tab_code = duckdb.sql("SELECT DISTINCT(tab_code) from cpi")
tab_code.show()
┌──────────┐
│ tab_code │
│  int64   │
├──────────┤
│        1 │
│        3 │
│        2 │
└──────────┘

オペレーション#

  • Relationからメソッドを実行してデータを操作できる

  • 実行結果はRelationで返される

集約関数を適用:

aggregate(expr, groups = {})

cpi.aggregate("min(tab_code), max(tab_code)")
┌───────────────┬───────────────┐
│ min(tab_code) │ max(tab_code) │
│     int64     │     int64     │
├───────────────┼───────────────┤
│             1 │             3 │
└───────────────┴───────────────┘

式を適用

project(expr)

tab_code.project("tab_code + 100")
┌──────────────────┐
│ (tab_code + 100) │
│      int64       │
├──────────────────┤
│              102 │
│              103 │
│              101 │
└──────────────────┘

n行を選択

limit(n, offset = 0)

tab_code.limit(2)
┌──────────┐
│ tab_code │
│  int64   │
├──────────┤
│        2 │
│        1 │
└──────────┘

ソート

order(expr)

tab_code.order("tab_code DESC")
┌──────────┐
│ tab_code │
│  int64   │
├──────────┤
│        3 │
│        2 │
│        1 │
└──────────┘

元のRelationにあり、relに存在しない行

except_(rel)

tab_code.except_(tab_code.limit(2))
┌──────────┐
│ tab_code │
│  int64   │
├──────────┤
│        2 │
└──────────┘

両方に存在する行

intersect(rel)

tab_code.intersect(tab_code.limit(2))
┌──────────┐
│ tab_code │
│  int64   │
├──────────┤
│        3 │
│        2 │
└──────────┘

結合

union(rel)

tab_code.union(tab_code.limit(2))
┌──────────┐
│ tab_code │
│  int64   │
├──────────┤
│        3 │
│        1 │
│        2 │
│        3 │
│        2 │
└──────────┘

条件に満たす行を抽出

filter(condition)

tab_code.filter("tab_code > 2")
┌──────────┐
│ tab_code │
│  int64   │
├──────────┤
│        3 │
└──────────┘

条件に基づいた結合

join(rel, condition, type = "inner")

r1 = duckdb.sql(
    "SELECT area_code, cat01_code, value FROM cpi WHERE time_code = '1970000303' AND cat01_code = 1"
).set_alias("r1")
r2 = duckdb.sql(
    "SELECT area_code, cat01_code, value FROM cpi WHERE time_code = '1970000404' AND cat01_code = 1"
).set_alias("r2")
r1.join(r2, "r1.area_code = r2.area_code")
┌───────────┬────────────┬────────┬───────────┬────────────┬────────┐
│ area_code │ cat01_code │ value  │ area_code │ cat01_code │ value  │
│  varchar  │   int64    │ double │  varchar  │   int64    │ double │
├───────────┼────────────┼────────┼───────────┼────────────┼────────┤
│ 13A01     │          1 │   31.2 │ 13A01     │          1 │    0.6 │
│ 00000     │          1 │   30.6 │ 00000     │          1 │    0.9 │
│ 00012     │          1 │   30.8 │ 00012     │          1 │    0.8 │
│ 00013     │          1 │   30.9 │ 00013     │          1 │    1.1 │
│ 00018     │          1 │   30.3 │ 00018     │          1 │    0.9 │
│ 00042     │          1 │   32.0 │ 00042     │          1 │    0.7 │
│ 00043     │          1 │   30.0 │ 00043     │          1 │    0.8 │
│ 00044     │          1 │   30.7 │ 00044     │          1 │    0.6 │
│ 00049     │          1 │   30.5 │ 00049     │          1 │    1.3 │
│ 00050     │          1 │   30.7 │ 00050     │          1 │    0.7 │
│   ·       │          · │     ·  │   ·       │          · │     ·  │
│   ·       │          · │     ·  │   ·       │          · │     ·  │
│   ·       │          · │     ·  │   ·       │          · │     ·  │
│ 40A02     │          1 │    1.2 │ 40A02     │          1 │   31.8 │
│ 41A01     │          1 │    0.6 │ 41A01     │          1 │   31.1 │
│ 42A01     │          1 │    1.0 │ 42A01     │          1 │   29.7 │
│ 43A01     │          1 │    1.1 │ 43A01     │          1 │   32.5 │
│ 44A01     │          1 │    0.7 │ 44A01     │          1 │   32.3 │
│ 45A01     │          1 │    0.7 │ 45A01     │          1 │   33.1 │
│ 46A01     │          1 │    0.7 │ 46A01     │          1 │   30.7 │
│ 40A01     │          1 │    0.5 │ 40A01     │          1 │   29.8 │
│ 31A01     │          1 │    0.8 │ 31A01     │          1 │   31.6 │
│ 37A01     │          1 │    0.4 │ 37A01     │          1 │   31.6 │
├───────────┴────────────┴────────┴───────────┴────────────┴────────┤
│ 240 rows (20 shown)                                     6 columns │
└───────────────────────────────────────────────────────────────────┘

または

See also

ColumnExpression :

Expression API

cols = [
    duckdb.ColumnExpression("area_code"),
    duckdb.ColumnExpression("cat01_code"),
    duckdb.ColumnExpression("value"),
]
r1 = (
    duckdb.sql("SELECT * FROM cpi")
    .filter("time_code = '1970000303' AND cat01_code = 1")
    .select(*cols)
).set_alias("r1")
r2 = (
    duckdb.sql("SELECT * FROM cpi")
    .filter("time_code = '1970000404' AND cat01_code = 1")
    .select(*cols)
).set_alias("r2")
r1.join(r2, "r1.area_code = r2.area_code")
┌───────────┬────────────┬────────┬───────────┬────────────┬────────┐
│ area_code │ cat01_code │ value  │ area_code │ cat01_code │ value  │
│  varchar  │   int64    │ double │  varchar  │   int64    │ double │
├───────────┼────────────┼────────┼───────────┼────────────┼────────┤
│ 13A01     │          1 │   31.2 │ 13A01     │          1 │    0.6 │
│ 00000     │          1 │   30.6 │ 00000     │          1 │    0.9 │
│ 00012     │          1 │   30.8 │ 00012     │          1 │    0.8 │
│ 00013     │          1 │   30.9 │ 00013     │          1 │    1.1 │
│ 00018     │          1 │   30.3 │ 00018     │          1 │    0.9 │
│ 00042     │          1 │   32.0 │ 00042     │          1 │    0.7 │
│ 00043     │          1 │   30.0 │ 00043     │          1 │    0.8 │
│ 00044     │          1 │   30.7 │ 00044     │          1 │    0.6 │
│ 00049     │          1 │   30.5 │ 00049     │          1 │    1.3 │
│ 00050     │          1 │   30.7 │ 00050     │          1 │    0.7 │
│   ·       │          · │     ·  │   ·       │          · │     ·  │
│   ·       │          · │     ·  │   ·       │          · │     ·  │
│   ·       │          · │     ·  │   ·       │          · │     ·  │
│ 40A02     │          1 │    1.2 │ 40A02     │          1 │   31.8 │
│ 41A01     │          1 │    0.6 │ 41A01     │          1 │   31.1 │
│ 42A01     │          1 │    1.0 │ 42A01     │          1 │   29.7 │
│ 43A01     │          1 │    1.1 │ 43A01     │          1 │   32.5 │
│ 44A01     │          1 │    0.7 │ 44A01     │          1 │   32.3 │
│ 45A01     │          1 │    0.7 │ 45A01     │          1 │   33.1 │
│ 46A01     │          1 │    0.7 │ 46A01     │          1 │   30.7 │
│ 40A01     │          1 │    0.5 │ 40A01     │          1 │   29.8 │
│ 31A01     │          1 │    0.8 │ 31A01     │          1 │   31.6 │
│ 37A01     │          1 │    0.4 │ 37A01     │          1 │   31.6 │
├───────────┴────────────┴────────┴───────────┴────────────┴────────┤
│ 240 rows (20 shown)                                     6 columns │
└───────────────────────────────────────────────────────────────────┘