⌘+k ctrl+k
1.1.3 (stable)
Search Shortcut cmd + k | ctrl + k
Relational API

关系API是一种替代API,可用于逐步构建查询。该API围绕DuckDBPyRelation节点展开。这些关系可以看作是SQL查询的符号表示。它们不持有任何数据——并且在调用触发执行的方法之前,不会执行任何操作。

构建关系

关系可以通过使用duckdb.sql方法从SQL查询中创建。或者,它们可以通过各种数据摄取方法(read_parquetread_csvread_json)创建。

例如,这里我们从SQL查询创建一个关系:

import duckdb

rel = duckdb.sql("SELECT * FROM range(10_000_000_000) tbl(id)")
rel.show()
┌────────────────────────┐
│           id           │
│         int64          │
├────────────────────────┤
│                      0 │
│                      1 │
│                      2 │
│                      3 │
│                      4 │
│                      5 │
│                      6 │
│                      7 │
│                      8 │
│                      9 │
│                      · │
│                      · │
│                      · │
│                   9990 │
│                   9991 │
│                   9992 │
│                   9993 │
│                   9994 │
│                   9995 │
│                   9996 │
│                   9997 │
│                   9998 │
│                   9999 │
├────────────────────────┤
│         ? rows         │
│ (>9999 rows, 20 shown) │
└────────────────────────┘

注意我们是如何构建一个计算大量数据(100亿行或74 GB数据)的关系的。这个关系是即时构建的——我们甚至可以即时打印这个关系。

当使用show打印关系或在终端中显示它时,会获取前10K行。如果有超过10K行,输出窗口将显示>9999 rows(因为关系中的行数未知)。

数据摄取

在SQL查询之外,提供了以下方法从外部数据构建关系对象。

  • from_arrow
  • from_df
  • read_csv
  • read_json
  • read_parquet

SQL查询

关系对象可以通过SQL进行查询,通过替换扫描。如果你有一个存储在变量中的关系对象,你可以像引用SQL表一样引用该变量(在FROM子句中)。这允许你使用关系对象逐步构建查询。

import duckdb

rel = duckdb.sql("SELECT * FROM range(1_000_000) tbl(id)")
duckdb.sql("SELECT sum(id) FROM rel").show()
┌──────────────┐
│   sum(id)    │
│    int128    │
├──────────────┤
│ 499999500000 │
└──────────────┘

操作

可以对关系执行许多操作。这些都是运行SQL查询的简写——并且它们本身将再次返回关系。

aggregate(expr, groups = {})

对关系应用一个(可选的)分组聚合。系统将自动对任何非聚合列进行分组。

import duckdb

rel = duckdb.sql("SELECT * FROM range(1_000_000) tbl(id)")
rel.aggregate("id % 2 AS g, sum(id), min(id), max(id)")
┌───────┬──────────────┬─────────┬─────────┐
│   g   │   sum(id)    │ min(id) │ max(id) │
│ int64 │    int128    │  int64  │  int64  │
├───────┼──────────────┼─────────┼─────────┤
│     0 │ 249999500000 │       0 │  999998 │
│     1 │ 250000000000 │       1 │  999999 │
└───────┴──────────────┴─────────┴─────────┘

except_(rel)

选择第一个关系中所有不在第二个关系中出现的行。这两个关系必须具有相同数量的列。

import duckdb

r1 = duckdb.sql("SELECT * FROM range(10) tbl(id)")
r2 = duckdb.sql("SELECT * FROM range(5) tbl(id)")
r1.except_(r2).show()
┌───────┐
│  id   │
│ int64 │
├───────┤
│     5 │
│     6 │
│     7 │
│     8 │
│     9 │
└───────┘

filter(condition)

将给定条件应用于关系,过滤掉不满足条件的任何行。

import duckdb

rel = duckdb.sql("SELECT * FROM range(1_000_000) tbl(id)")
rel.filter("id > 5").limit(3).show()
┌───────┐
│  id   │
│ int64 │
├───────┤
│     6 │
│     7 │
│     8 │
└───────┘

intersect(rel)

选择两个关系的交集——返回在两个关系中同时出现的所有行。关系必须具有相同数量的列。

import duckdb

r1 = duckdb.sql("SELECT * FROM range(10) tbl(id)")
r2 = duckdb.sql("SELECT * FROM range(5) tbl(id)")
r1.intersect(r2).show()
┌───────┐
│  id   │
│ int64 │
├───────┤
│     0 │
│     1 │
│     2 │
│     3 │
│     4 │
└───────┘

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

合并两个关系,根据提供的条件进行连接。

import duckdb

r1 = duckdb.sql("SELECT * FROM range(5) tbl(id)").set_alias("r1")
r2 = duckdb.sql("SELECT * FROM range(10, 15) tbl(id)").set_alias("r2")
r1.join(r2, "r1.id + 10 = r2.id").show()
┌───────┬───────┐
│  id   │  id   │
│ int64 │ int64 │
├───────┼───────┤
│     0 │    10 │
│     1 │    11 │
│     2 │    12 │
│     3 │    13 │
│     4 │    14 │
└───────┴───────┘

limit(n, offset = 0)

选择前n行,可选地偏移offset

import duckdb

rel = duckdb.sql("SELECT * FROM range(1_000_000) tbl(id)")
rel.limit(3).show()
┌───────┐
│  id   │
│ int64 │
├───────┤
│     0 │
│     1 │
│     2 │
└───────┘

order(expr)

按给定的表达式集对关系进行排序。

import duckdb

rel = duckdb.sql("SELECT * FROM range(1_000_000) tbl(id)")
rel.order("id DESC").limit(3).show()
┌────────┐
│   id   │
│ int64  │
├────────┤
│ 999999 │
│ 999998 │
│ 999997 │
└────────┘

project(expr)

将给定的表达式应用于关系中的每一行。

import duckdb

rel = duckdb.sql("SELECT * FROM range(1_000_000) tbl(id)")
rel.project("id + 10 AS id_plus_ten").limit(3).show()
┌─────────────┐
│ id_plus_ten │
│    int64    │
├─────────────┤
│          10 │
│          11 │
│          12 │
└─────────────┘

union(rel)

合并两个关系,返回r1中的所有行,然后是r2中的所有行。这些关系必须具有相同数量的列。

import duckdb

r1 = duckdb.sql("SELECT * FROM range(5) tbl(id)")
r2 = duckdb.sql("SELECT * FROM range(10, 15) tbl(id)")
r1.union(r2).show()
┌───────┐
│  id   │
│ int64 │
├───────┤
│     0 │
│     1 │
│     2 │
│     3 │
│     4 │
│    10 │
│    11 │
│    12 │
│    13 │
│    14 │
└───────┘

结果输出

关系的结果可以转换为各种类型的Python结构,更多信息请参见结果转换页面

关系的结果也可以使用以下方法直接写入文件。