Relational API#
インクリメンタルにクエリを構築
DuckDBPyRelationノードから呼び出すSQLクエリをシンボリックに表現
実行のトリガーとなるメソッドが呼び出されるまで、リレーションはデータを保持・実行しない
Relationの作成#
sqlfrom_arrowfrom_dfread_csvread_jsonread_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 │
└───────────────────────────────────────────────────────────────────┘
または
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 │
└───────────────────────────────────────────────────────────────────┘