Отношения API
API Отношений — это альтернативный API, который можно использовать для поэтапного построения запросов. API ориентирован на узлы DuckDBPyRelation. Отношения можно рассматривать как символические представления SQL-запросов. Они не хранят данные — и ничего не выполняется — до тех пор, пока не будет вызван метод, запускающий выполнение.
Построение отношений
Отношения могут быть созданы из SQL-запросов с использованием метода duckdb.sql. Кроме того, они могут быть созданы с помощью различных методов загрузки данных (read_parquet, read_csv, read_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) │ └────────────────────────┘
Обратите внимание, как мы строим отношение, которое вычисляет огромное количество данных (10 млрд строк или 74 ГБ данных). Отношение строится мгновенно — и мы можем даже мгновенно вывести отношение.
При выводе отношения с помощью show или отображении его в терминале извлекаются первые 10K строк. Если строк больше, чем 10K, в окне вывода будет отображаться >9999 rows (поскольку количество строк в отношении неизвестно).
Загрузка данных
Вне SQL-запросов для построения объектов отношений из внешних данных предоставляются следующие методы.
from_arrowfrom_dfread_csvread_jsonread_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 строк, необязательно смещая их на смещение.
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, см. страницу преобразования результатов для получения дополнительной информации.
Результат отношений также можно напрямую записать в файлы с помощью следующих методов.
© Copyright 2018–2024 Stichting DuckDB Foundation
Licensed under the MIT License.
https://duckdb.org/docs/api/python/relational_api.html