The Relational API builds a query one step at a time from Python.
A relation, a DuckDBPyRelation, is a piece of SQL text: the methods of the Transformation and Functions sections return a new relation whose text extends the one they were called on.
Lazy Evaluation
Building a relation runs nothing: DuckDB binds the text once to learn the columns and their types, and holds no data. For example, a relation over a billion rows is built at once:
import duckdb
duckdb_conn = duckdb.connect()
rel = duckdb_conn.sql("FROM range(1_000_000_000) t(id) SELECT id, id % 7 AS bucket")
print(rel.sql_query())
FROM range(1_000_000_000) t(id) SELECT id, id % 7 AS bucket
sql_query() returns exactly the text that runs.
The query runs when a method of the Output section reads the relation, and it runs again on every read, so each read sees the current data.
Printing a relation, or calling show(), also runs it and displays the first rows:
import duckdb
duckdb_conn = duckdb.connect()
rel = duckdb_conn.sql("FROM range(1_000_000_000) t(id) SELECT id, id % 7 AS bucket")
rel.filter("bucket = 3").order("id").limit(3).show()
┌───────┬────────┐
│ id │ bucket │
│ int64 │ int64 │
├───────┼────────┤
│ 3 │ 3 │
│ 10 │ 3 │
│ 17 │ 3 │
└───────┴────────┘
Only a statement that reads, such as a SELECT, gives a lazy relation.
Any other statement passed to sql(), such as CREATE TABLE or INSERT, runs at the call, and the relation holds what it returned.
The params list or dict is copied when the relation is created, and its values are converted each time the relation runs.
A column is also an attribute of the relation, as in rel.price, unless a method has its name: a column called offset is reached as rel["offset"], since rel.offset is the offset() method.
To run a query once and keep its rows, call materialize():
import duckdb
duckdb_conn = duckdb.connect()
duckdb_conn.sql("CREATE TABLE items (id INTEGER)")
counted = duckdb_conn.sql("SELECT count(*) AS n FROM items")
held = counted.materialize()
duckdb_conn.sql("INSERT INTO items VALUES (1), (2)")
print(counted.fetchall(), held.fetchall())
[(2,)] [(0,)]
Relation Creation
This section contains the details on how a relation is created. A relation over a query that reads is lazy evaluated.
| Name | Description |
|---|---|
from_arrow |
Create a relation object from an Arrow object. |
from_csv_auto |
Alias of read_csv(). |
from_df |
Create a relation object from the DataFrame in df. |
from_parquet |
Alias of read_parquet(). |
from_query |
Alias of sql(). |
query |
Alias of sql(). |
read_csv |
Create a relation object from the CSV file in 'name'. |
read_json |
Create a relation object from the JSON file in 'name'. |
read_parquet |
Create a relation object from the Parquet path(s) or file-like object(s) in 'path_or_buffer'. |
sql |
Run a SQL query. A statement that only reads returns a relation that runs the query each time it is read, parameter values bound at every run. Any other statement runs once, now, and gives a relation over what it returned. Statements before the last one run immediately. |
table |
Create a relation object for the named table. |
table_function |
Create a relation object from the named table function with given parameters. |
values |
Create a relation object from the passed values. |
view |
Create a relation object for the named view. |
from_arrow
from_arrow(self: _duckdb.DuckDBPyConnection, arrow_object: object) -> DuckDBPyRelation
Create a relation object from an Arrow object.
Parameters
-
arrow_object : object
The Arrow object to create a relation from: a table, a record batch, a record batch reader, a dataset, a scanner, a polars DataFrame or an object that exports the Arrow PyCapsule interface.
Example
import duckdb
import pyarrow as pa
ids = pa.array([1], type=pa.int8())
texts = pa.array(['a'], type=pa.string())
example_table = pa.table([ids, texts], names=["id", "text"])
duckdb_conn = duckdb.connect()
rel = duckdb_conn.from_arrow(example_table)
rel.show()
Result
┌──────┬─────────┐
│ id │ text │
│ int8 │ varchar │
├──────┼─────────┤
│ 1 │ a │
└──────┴─────────┘
from_csv_auto
from_csv_auto(self: _duckdb.DuckDBPyConnection, *args: object, **kwargs: object) -> DuckDBPyRelation
Alias of read_csv().
from_df
from_df(self: _duckdb.DuckDBPyConnection, df: object) -> DuckDBPyRelation
Create a relation object from the DataFrame in df.
Parameters
-
df : pandas.DataFrame
A pandas DataFrame to be converted into a DuckDB relation.
Example
import duckdb
import pandas as pd
df = pd.DataFrame(data = {'id': [1], "text":["a"]})
duckdb_conn = duckdb.connect()
rel = duckdb_conn.from_df(df)
rel.show()
Result
┌───────┬─────────┐
│ id │ text │
│ int64 │ varchar │
├───────┼─────────┤
│ 1 │ a │
└───────┴─────────┘
from_parquet
from_parquet(self: _duckdb.DuckDBPyConnection, path_or_buffer: object, binary_as_string: bool = False, **kwargs: Any) -> DuckDBPyRelation
Alias of read_parquet().
from_query
from_query(self: _duckdb.DuckDBPyConnection, query: object, *, alias: str = '', params: object = None) -> DuckDBPyRelation | None
Alias of sql().
query
query(self: _duckdb.DuckDBPyConnection, query: object, *, alias: str = '', params: object = None) -> DuckDBPyRelation | None
Alias of sql().
read_csv
read_csv(self: _duckdb.DuckDBPyConnection, *args: object, **kwargs: object) -> DuckDBPyRelation
Create a relation object from the CSV file in 'name'.
The options other than path_or_buffer are keyword arguments; an unknown one raises InvalidInputException. Most are the option of the same name of the SQL read_csv function; sep and delimiter are delim, dtype is dtypes, na_values is nullstr, skiprows is skip, quotechar is quote, escapechar is escape, date_format is dateformat, timestamp_format is timestampformat, lineterminator is new_line and decimal is decimal_separator.
Aliases: from_csv_auto
Parameters
-
path_or_buffer : str, list[str], file-like object
Path to the file, a glob pattern, a list of paths or a file-like object such as
io.StringIOorio.BytesIO. -
header : bool, int, keyword-only, default: None
Whether the first line holds the column names;
0meansTrue. Detected when omitted. -
compression : str, keyword-only, default: None
Compression of the files:
'none','gzip'or'zstd'. Detected from the file extension when omitted. -
sep : str, keyword-only, default: None
Delimiter between the columns, up to 4 bytes; cannot be combined with
delimiter. Detected when omitted. -
delimiter : str, keyword-only, default: None
Same as
sep. -
dtype : dict[str, str], list[str], keyword-only, default: None
Column types, as a dict of column name to type or a list of types by position; a type is a type name or a
DuckDBPyType. -
na_values : str, list[str], keyword-only, default: None
Strings that are read as
NULL. -
skiprows : int, keyword-only, default: None
Number of lines to skip at the start of each file.
-
quotechar : str, keyword-only, default: None
Character used to quote values.
-
escapechar : str, keyword-only, default: None
Character that escapes the quote character inside a quoted value.
-
comment : str, keyword-only, default: None
Character that starts a comment: a line is read only up to it, and a line that starts with it is skipped.
-
thousands : str, keyword-only, default: None
Character that separates the thousands in numbers; it must differ from
decimal. -
encoding : str, keyword-only, default: None
Only UTF-8 is accepted, written
'utf-8'or'utf8'; any other encoding raisesBinderException. -
parallel : bool, keyword-only, default: None
Whether to use the parallel CSV reader.
-
date_format : str, keyword-only, default: None
Format used to parse dates.
-
timestamp_format : str, keyword-only, default: None
Format used to parse timestamps.
-
sample_size : int, keyword-only, default: None
Number of lines sampled to detect the dialect and the types.
-
files_to_sniff : int, keyword-only, default: None
Number of files sampled to detect the schema when reading several files;
-1samples all of them. -
auto_detect : bool, keyword-only, default: None
Whether to detect the dialect, the header and the types. Detected when omitted.
-
all_varchar : bool, keyword-only, default: None
Read every column as
VARCHAR, without detecting the types. -
normalize_names : bool, keyword-only, default: None
Normalize the column names; for example,
My Colbecomesmy_col. -
null_padding : bool, keyword-only, default: None
Pad a line that lacks columns with
NULLvalues on the right. -
strict_mode : bool, keyword-only, default: None
Whether to refuse a file that is not structurally valid CSV; with
False, the reader tries to read it anyway. -
names : list[str], keyword-only, default: None
Column names, as a list.
-
lineterminator : str, CSVLineTerminator, keyword-only, default: None
The line ending: one of
duckdb.CSVLineTerminator.LINE_FEED,duckdb.CSVLineTerminator.CARRIAGE_RETURN_LINE_FEED,'\\n'and'\\r\\n', the last two being escape text as written in Python; a string that holds the newline character itself, such as'\n', is refused. -
columns : dict[str, str], keyword-only, default: None
Column names and types, as a dict of column name to type name; the types are then not detected.
-
auto_type_candidates : list[str], keyword-only, default: None
Types the reader may choose from when it detects the column types;
VARCHARis always one of them. -
max_line_size : int, str, keyword-only, default: None
Maximum line size, in bytes.
-
ignore_errors : bool, keyword-only, default: None
Skip the lines that fail to parse.
-
store_rejects : bool, keyword-only, default: None
Skip the lines with errors and store them in the rejects table.
-
rejects_table : str, keyword-only, default: None
Name of the temporary table that holds the faulty lines.
-
rejects_scan : str, keyword-only, default: None
Name of the temporary table that holds information on the scans that found faulty lines.
-
rejects_limit : int, keyword-only, default: None
Maximum number of faulty lines stored for each file;
0means no limit. -
force_not_null : list[str], keyword-only, default: None
Columns whose values are never read as
NULL. -
buffer_size : int, keyword-only, default: None
Size of the buffers used to read the files, in bytes.
-
decimal : str, keyword-only, default: None
Decimal separator of numbers.
-
allow_quoted_nulls : bool, keyword-only, default: None
Whether a quoted value can be read as
NULL. -
filename : bool, keyword-only, default: None
Add a column
filenamewith the path of the file each row came from. -
hive_partitioning : bool, keyword-only, default: None
Interpret the path as a Hive partitioned path.
-
union_by_name : bool, keyword-only, default: None
Align the columns of several files by name instead of by position.
-
hive_types : dict[str, str], keyword-only, default: None
Types of the Hive partition columns, as a dict of column name to type name.
-
hive_types_autocast : bool, keyword-only, default: None
Whether to detect the types of the Hive partition columns.
Example
import csv
import duckdb
duckdb_conn = duckdb.connect()
with open('code_example.csv', 'w', newline='') as csvfile:
fieldnames = ['id', 'text']
writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
writer.writeheader()
writer.writerow({'id': '1', 'text': 'a'})
rel = duckdb_conn.read_csv("code_example.csv")
rel.show()
Result
┌───────┬─────────┐
│ id │ text │
│ int64 │ varchar │
├───────┼─────────┤
│ 1 │ a │
└───────┴─────────┘
read_json
read_json(self: _duckdb.DuckDBPyConnection, path_or_buffer: object, **kwargs: Any) -> DuckDBPyRelation
Create a relation object from the JSON file in 'name'.
The options other than path_or_buffer are keyword arguments; an unknown one raises TypeError. Each is the option of the same name of the SQL read_json function.
Parameters
-
path_or_buffer : str, list[str], file-like object
Path to the file, a glob pattern, a list of paths or a file-like object such as
io.StringIOorio.BytesIO. -
columns : dict[str, str], keyword-only, default: None
Key names and types, as a dict of key name to type name; the schema is then not detected.
-
sample_size : int, keyword-only, default: None
Number of objects sampled to detect the types;
-1samples all of them. -
maximum_depth : int, keyword-only, default: None
Maximum nesting depth to which the types are detected;
-1detects all levels. -
records : str, keyword-only, default: None
'true'to read each object as a row of columns,'false'to read each as one value,'auto'to detect it. -
format : str, keyword-only, default: None
'auto','unstructured','newline_delimited'or'array'. -
date_format : str, keyword-only, default: None
Format used to parse dates.
-
timestamp_format : str, keyword-only, default: None
Format used to parse timestamps.
-
compression : str, keyword-only, default: None
Compression of the files:
'none','gzip','zstd'or'auto_detect'. Detected from the file extension when omitted. -
maximum_object_size : int, keyword-only, default: None
Maximum size of a JSON object, in bytes.
-
ignore_errors : bool, keyword-only, default: None
Read the objects that fail to parse as
NULLrows; only withformat='newline_delimited'. -
convert_strings_to_integers : bool, keyword-only, default: None
Whether strings that hold integers are read as numbers.
-
field_appearance_threshold : float, keyword-only, default: None
When the fields of an object appear, on average, in a smaller fraction of the sampled objects than this, the object is read as a
MAP. -
map_inference_threshold : int, keyword-only, default: None
An object with more fields than this is read as a
MAPinstead of aSTRUCT;-1never reads aMAP. -
maximum_sample_files : int, keyword-only, default: None
Maximum number of files sampled to detect the schema.
-
filename : bool, keyword-only, default: None
Add a column
filenamewith the path of the file each row came from. -
hive_partitioning : bool, keyword-only, default: None
Interpret the path as a Hive partitioned path.
-
union_by_name : bool, keyword-only, default: None
Align the columns of several files by name instead of by position.
-
hive_types : dict[str, str], keyword-only, default: None
Types of the Hive partition columns, as a dict of column name to type name.
-
hive_types_autocast : bool, keyword-only, default: None
Whether to detect the types of the Hive partition columns.
Example
import duckdb
import json
with open("code_example.json", mode="w") as f:
json.dump([{'id': 1, "text":"a"}], f)
duckdb_conn = duckdb.connect()
rel = duckdb_conn.read_json("code_example.json")
rel.show()
Result
┌───────┬─────────┐
│ id │ text │
│ int64 │ varchar │
├───────┼─────────┤
│ 1 │ a │
└───────┴─────────┘
read_parquet
read_parquet(self: _duckdb.DuckDBPyConnection, path_or_buffer: object, binary_as_string: bool = False, **kwargs: Any) -> DuckDBPyRelation
Create a relation object from the Parquet path(s) or file-like object(s) in 'path_or_buffer'.
Each option is the option of the same name of the SQL read_parquet function.
Aliases: from_parquet
Parameters
-
path_or_buffer : str, list[str], file-like object
Path to the Parquet file, a glob pattern, a list of paths or a file object opened in binary mode.
-
binary_as_string : bool, default: False
Read binary columns as strings, for files from writers that do not mark their strings as UTF-8.
-
file_row_number : bool, keyword-only, default: False
Add a column
file_row_numberwith the number of each row within its file. -
filename : bool, keyword-only, default: False
Add a column
filenamewith the path of the file each row came from. -
hive_partitioning : bool, keyword-only, default: False
Interpret the path as a Hive partitioned path.
-
union_by_name : bool, keyword-only, default: False
Align the columns of several files by name instead of by position.
-
compression : str, keyword-only, default: None
Accepted and ignored: a Parquet file records its own compression.
Example
import duckdb
import pyarrow as pa
import pyarrow.parquet as pq
ids = pa.array([1], type=pa.int8())
texts = pa.array(['a'], type=pa.string())
example_table = pa.table([ids, texts], names=["id", "text"])
pq.write_table(example_table, "code_example.parquet")
duckdb_conn = duckdb.connect()
rel = duckdb_conn.read_parquet("code_example.parquet")
rel.show()
Result
┌──────┬─────────┐
│ id │ text │
│ int8 │ varchar │
├──────┼─────────┤
│ 1 │ a │
└──────┴─────────┘
sql
sql(self: _duckdb.DuckDBPyConnection, query: object, *, alias: str = '', params: object = None) -> DuckDBPyRelation | None
Run a SQL query. A statement that only reads returns a relation that runs the query each time it is read, parameter values bound at every run. Any other statement runs once, now, and gives a relation over what it returned. Statements before the last one run immediately.
Aliases: from_query, query
Parameters
-
query : str
The SQL text; when it holds several statements, the ones before the last run at the call.
-
alias : str, keyword-only, default: ''
Alias of the relation.
-
params : list, dict, keyword-only, default: None
Values of the query parameters: a list for
?and$1markers, a dict for$namemarkers. The list or dict is copied at the call, as is any list, tuple or dict inside it; the values in it are converted each time the relation runs, so abytearraychanged in place afterwards is read changed.
Example
import duckdb
duckdb_conn = duckdb.connect()
rel = duckdb_conn.sql("SELECT * FROM range(1, 4) tbl(id) WHERE id > $minimum", params={"minimum": 1})
rel.show()
Result
┌───────┐
│ id │
│ int64 │
├───────┤
│ 2 │
│ 3 │
└───────┘
table
table(self: _duckdb.DuckDBPyConnection, table_name: str) -> DuckDBPyRelation
Create a relation object for the named table.
Parameters
-
table_name : str
Name of the table to create a relation from.
Example
import duckdb
duckdb_conn = duckdb.connect()
duckdb_conn.sql("CREATE TABLE code_example AS SELECT * FROM range(1, 2) tbl(id)")
rel = duckdb_conn.table("code_example")
rel.show()
Result
┌───────┐
│ id │
│ int64 │
├───────┤
│ 1 │
└───────┘
table_function
table_function(self: _duckdb.DuckDBPyConnection, name: str, parameters: object = None) -> DuckDBPyRelation
Create a relation object from the named table function with given parameters.
Parameters
-
name : str
Name of the table function to call.
-
parameters : list, default: None
The arguments to pass to the table function, as a list.
Example
import duckdb
duckdb_conn = duckdb.connect()
duckdb_conn.sql("""
CREATE MACRO get_record_for(x) AS TABLE
SELECT x * range AS result FROM range(1, 2)
""")
rel = duckdb_conn.table_function(name="get_record_for", parameters=[1])
rel.show()
Result
┌────────┐
│ result │
│ int64 │
├────────┤
│ 1 │
└────────┘
values
values(self: _duckdb.DuckDBPyConnection, *args: object) -> DuckDBPyRelation
Create a relation object from the passed values.
Python values are converted once, at the call, so a later change to the Python objects does not change the relation. Such a relation reads rows held in this process, which create_view() refuses.
Parameters
-
*args : list, tuple, object
The rows: one list holding the values of one row, several tuples for several rows or the values of one row as separate arguments. A value is a Python value or an Expression.
Example
import duckdb
duckdb_conn = duckdb.connect()
rel = duckdb_conn.values([1, 'a'])
rel.show()
Result
┌───────┬─────────┐
│ col0 │ col1 │
│ int32 │ varchar │
├───────┼─────────┤
│ 1 │ a │
└───────┴─────────┘
view
view(self: _duckdb.DuckDBPyConnection, view_name: str) -> DuckDBPyRelation
Create a relation object for the named view.
Parameters
-
view_name : str
Name of the view to create a relation from.
Example
import duckdb
duckdb_conn = duckdb.connect()
duckdb_conn.sql("CREATE VIEW code_example AS SELECT * FROM range(1, 2) tbl(id)")
rel = duckdb_conn.view("code_example")
rel.show()
Result
┌───────┐
│ id │
│ int64 │
├───────┤
│ 1 │
└───────┘
Relation Definition Details
This section contains the details on how to inspect a relation.
| Name | Description |
|---|---|
alias |
Get the name of the current alias. |
columns |
Return a list containing the names of the columns of the relation. |
describe |
Gives basic statistics (e.g., min, max) and if NULL exists for each column of the relation. |
description |
Return the description of the result. |
dtypes |
Alias of types. |
explain |
The plan the engine runs for this relation, as text; under Jupyter the default is shown as HTML. |
preview |
The first limit rows drawn as a table, with the footer __repr__ prints for the relation. |
query |
Run the given SQL query in sql_query on the view named virtual_table_name that refers to the relation object. |
set_alias |
Rename the relation object to new alias. |
shape |
Tuple of # of rows, # of columns in relation. |
show |
Display a summary of the data. |
sql_query |
Get the SQL query that is equivalent to the relation; values given as params= stay markers. |
type |
Get the type of the relation. |
types |
Return a list containing the types of the columns of the relation. |
alias
Get the name of the current alias.
Example
import duckdb
duckdb_conn = duckdb.connect()
rel = duckdb_conn.sql("""
SELECT *
FROM (VALUES
(1, 'jeans', 'clothing', 20, TRUE),
(2, 't-shirt', 'clothing', 8, FALSE),
(3, 'jacket', 'clothing', 65, TRUE),
(4, 'hammer', 'tools', 42, TRUE),
(5, 'screwdriver', 'tools', 7, TRUE),
(6, 'drill', 'tools', 89, TRUE)
) AS items(id, item, category, price, in_stock)
""")
rel.set_alias("my_relation").alias
Result
'my_relation'
columns
Return a list containing the names of the columns of the relation.
Example
import duckdb
duckdb_conn = duckdb.connect()
rel = duckdb_conn.sql("""
SELECT *
FROM (VALUES
(1, 'jeans', 'clothing', 20, TRUE),
(2, 't-shirt', 'clothing', 8, FALSE),
(3, 'jacket', 'clothing', 65, TRUE),
(4, 'hammer', 'tools', 42, TRUE),
(5, 'screwdriver', 'tools', 7, TRUE),
(6, 'drill', 'tools', 89, TRUE)
) AS items(id, item, category, price, in_stock)
""")
rel.columns
Result
['id', 'item', 'category', 'price', 'in_stock']
describe
describe(self) -> DuckDBPyRelation
Gives basic statistics (e.g., min, max) and if NULL exists for each column of the relation.
Example
import duckdb
duckdb_conn = duckdb.connect()
rel = duckdb_conn.sql("""
SELECT *
FROM (VALUES
(1, 'jeans', 'clothing', 20, TRUE),
(2, 't-shirt', 'clothing', 8, FALSE),
(3, 'jacket', 'clothing', 65, TRUE),
(4, 'hammer', 'tools', 42, TRUE),
(5, 'screwdriver', 'tools', 7, TRUE),
(6, 'drill', 'tools', 89, TRUE)
) AS items(id, item, category, price, in_stock)
""")
rel.describe()
Result
┌─────────┬────────────────────┬─────────┬──────────┬───────────────────┬──────────┐
│ aggr │ id │ item │ category │ price │ in_stock │
│ varchar │ double │ varchar │ varchar │ double │ varchar │
├─────────┼────────────────────┼─────────┼──────────┼───────────────────┼──────────┤
│ count │ 6.0 │ 6 │ 6 │ 6.0 │ 6 │
│ mean │ 3.5 │ NULL │ NULL │ 38.5 │ NULL │
│ stddev │ 1.8708286933869707 │ NULL │ NULL │ 33.25507480069771 │ NULL │
│ min │ 1.0 │ drill │ clothing │ 7.0 │ false │
│ max │ 6.0 │ t-shirt │ tools │ 89.0 │ true │
│ median │ 3.5 │ NULL │ NULL │ 31.0 │ NULL │
└─────────┴────────────────────┴─────────┴──────────┴───────────────────┴──────────┘
description
Return the description of the result.
Example
import duckdb
duckdb_conn = duckdb.connect()
rel = duckdb_conn.sql("""
SELECT *
FROM (VALUES
(1, 'jeans', 'clothing', 20, TRUE),
(2, 't-shirt', 'clothing', 8, FALSE),
(3, 'jacket', 'clothing', 65, TRUE),
(4, 'hammer', 'tools', 42, TRUE),
(5, 'screwdriver', 'tools', 7, TRUE),
(6, 'drill', 'tools', 89, TRUE)
) AS items(id, item, category, price, in_stock)
""")
rel.description
Result
[('id', INTEGER, None, None, None, None, None), ('item', VARCHAR, None, None, None, None, None), ('category', VARCHAR, None, None, None, None, None), ('price', INTEGER, None, None, None, None, None), ('in_stock', BOOLEAN, None, None, None, None, None)]
dtypes
Alias of types.
explain
explain(self, type: object = ExplainType.STANDARD, format: str | None = None, *, analyze: bool = False) -> str
The plan the engine runs for this relation, as text; under Jupyter the default is shown as HTML.
With analyze=True or with type set to 'analyze' or duckdb.ExplainType.ANALYZE, the query runs and the plan shows the rows and the time of each operator, as EXPLAIN ANALYZE does.
Parameters
-
type : str, ExplainType, default: ExplainType.STANDARD
'standard'orduckdb.ExplainType.STANDARDfor the plan,'analyze'orduckdb.ExplainType.ANALYZEto run the query and profile it. -
format : str, default: None
The output format, such as
'text','json','html','graphviz'or'yaml'. The default draws the plan as text, and as HTML under Jupyter. -
analyze : bool, keyword-only, default: False
Run the query and profile it, as
type='analyze'does.
Example
import duckdb
duckdb_conn = duckdb.connect()
rel = duckdb_conn.sql("""
SELECT *
FROM (VALUES
(1, 'jeans', 'clothing', 20, TRUE),
(2, 't-shirt', 'clothing', 8, FALSE),
(3, 'jacket', 'clothing', 65, TRUE),
(4, 'hammer', 'tools', 42, TRUE),
(5, 'screwdriver', 'tools', 7, TRUE),
(6, 'drill', 'tools', 89, TRUE)
) AS items(id, item, category, price, in_stock)
""")
print(rel.explain())
Result
╭─ Column Data Scan ─╮
│ ~6 rows │
╰────────────────────╯
preview
preview(self, limit: int = 10) -> str
The first limit rows drawn as a table, with the footer __repr__ prints for the relation.
Parameters
-
limit : int, default: 10
The number of rows to draw.
Example
import duckdb
duckdb_conn = duckdb.connect()
rel = duckdb_conn.sql("""
SELECT *
FROM (VALUES
(1, 'jeans', 'clothing', 20, TRUE),
(2, 't-shirt', 'clothing', 8, FALSE),
(3, 'jacket', 'clothing', 65, TRUE),
(4, 'hammer', 'tools', 42, TRUE),
(5, 'screwdriver', 'tools', 7, TRUE),
(6, 'drill', 'tools', 89, TRUE)
) AS items(id, item, category, price, in_stock)
""")
print(rel.preview(3))
Result
┌───────┬─────────┬──────────┬───────┬──────────┐
│ id │ item │ category │ price │ in_stock │
│ int32 │ varchar │ varchar │ int32 │ boolean │
├───────┼─────────┼──────────┼───────┼──────────┤
│ 1 │ jeans │ clothing │ 20 │ true │
│ 2 │ t-shirt │ clothing │ 8 │ false │
│ 3 │ jacket │ clothing │ 65 │ true │
└───────┴─────────┴──────────┴───────┴──────────┘
query
query(self, virtual_table_name: str, sql_query: str) -> DuckDBPyRelation | None
Run the given SQL query in sql_query on the view named virtual_table_name that refers to the relation object.
The name is this query's own: it is a common table expression over the relation, and a catalog entry for the length of the call, so a table function or a query that defines the name itself can bind against it. Nothing of it is left afterwards. A statement that does not only read, which includes a SELECT whose common table expression writes, runs at the call and the relation holds what it returned.
Parameters
-
virtual_table_name : str
The name under which
sql_queryreads the relation. -
sql_query : str
The SQL query, a single statement, that reads the relation by the name
virtual_table_name.
Example
import duckdb
duckdb_conn = duckdb.connect()
rel = duckdb_conn.sql("""
SELECT *
FROM (VALUES
(1, 'jeans', 'clothing', 20, TRUE),
(2, 't-shirt', 'clothing', 8, FALSE),
(3, 'jacket', 'clothing', 65, TRUE),
(4, 'hammer', 'tools', 42, TRUE),
(5, 'screwdriver', 'tools', 7, TRUE),
(6, 'drill', 'tools', 89, TRUE)
) AS items(id, item, category, price, in_stock)
""")
rel.query(virtual_table_name="items", sql_query="SELECT max(price) AS max_price FROM items")
Result
┌───────────┐
│ max_price │
│ int32 │
├───────────┤
│ 89 │
└───────────┘
set_alias
set_alias(self, alias: str) -> DuckDBPyRelation
Rename the relation object to new alias.
Parameters
-
alias : str
The alias name to assign to the relation.
Example
import duckdb
duckdb_conn = duckdb.connect()
rel = duckdb_conn.sql("""
SELECT *
FROM (VALUES
(1, 'jeans', 'clothing', 20, TRUE),
(2, 't-shirt', 'clothing', 8, FALSE),
(3, 'jacket', 'clothing', 65, TRUE),
(4, 'hammer', 'tools', 42, TRUE),
(5, 'screwdriver', 'tools', 7, TRUE),
(6, 'drill', 'tools', 89, TRUE)
) AS items(id, item, category, price, in_stock)
""")
rel.set_alias("items").select("items.item, items.price")
Result
┌─────────────┬───────┐
│ item │ price │
│ varchar │ int32 │
├─────────────┼───────┤
│ jeans │ 20 │
│ t-shirt │ 8 │
│ jacket │ 65 │
│ hammer │ 42 │
│ screwdriver │ 7 │
│ drill │ 89 │
└─────────────┴───────┘
shape
Tuple of # of rows, # of columns in relation.
Example
import duckdb
duckdb_conn = duckdb.connect()
rel = duckdb_conn.sql("""
SELECT *
FROM (VALUES
(1, 'jeans', 'clothing', 20, TRUE),
(2, 't-shirt', 'clothing', 8, FALSE),
(3, 'jacket', 'clothing', 65, TRUE),
(4, 'hammer', 'tools', 42, TRUE),
(5, 'screwdriver', 'tools', 7, TRUE),
(6, 'drill', 'tools', 89, TRUE)
) AS items(id, item, category, price, in_stock)
""")
rel.shape
Result
(6, 5)
show
show(self, *, max_width: int | None = None, max_rows: int | None = None, max_col_width: int | None = None, null_value: str | None = None, render_mode: object = None) -> None
Display a summary of the data.
Parameters
-
max_width : int, keyword-only, default: None
Maximum display width for the entire output in characters.
-
max_rows : int, keyword-only, default: None
Maximum number of rows to display.
-
max_col_width : int, keyword-only, default: None
Maximum number of characters to display per column.
-
null_value : str, keyword-only, default: None
String to display in place of NULL values.
-
render_mode : RenderMode, keyword-only, default: None
duckdb.RenderMode.ROWSto draw a row per line,duckdb.RenderMode.COLUMNSto draw a column per line.
Example
import duckdb
duckdb_conn = duckdb.connect()
rel = duckdb_conn.sql("""
SELECT *
FROM (VALUES
(1, 'jeans', 'clothing', 20, TRUE),
(2, 't-shirt', 'clothing', 8, FALSE),
(3, 'jacket', 'clothing', 65, TRUE),
(4, 'hammer', 'tools', 42, TRUE),
(5, 'screwdriver', 'tools', 7, TRUE),
(6, 'drill', 'tools', 89, TRUE)
) AS items(id, item, category, price, in_stock)
""")
rel.show()
Result
┌───────┬─────────────┬──────────┬───────┬──────────┐
│ id │ item │ category │ price │ in_stock │
│ int32 │ varchar │ varchar │ int32 │ boolean │
├───────┼─────────────┼──────────┼───────┼──────────┤
│ 1 │ jeans │ clothing │ 20 │ true │
│ 2 │ t-shirt │ clothing │ 8 │ false │
│ 3 │ jacket │ clothing │ 65 │ true │
│ 4 │ hammer │ tools │ 42 │ true │
│ 5 │ screwdriver │ tools │ 7 │ true │
│ 6 │ drill │ tools │ 89 │ true │
└───────┴─────────────┴──────────┴───────┴──────────┘
sql_query
sql_query(self) -> str
Get the SQL query that is equivalent to the relation; values given as params= stay markers.
Example
import duckdb
duckdb_conn = duckdb.connect()
rel = duckdb_conn.sql("""
SELECT *
FROM (VALUES
(1, 'jeans', 'clothing', 20, TRUE),
(2, 't-shirt', 'clothing', 8, FALSE),
(3, 'jacket', 'clothing', 65, TRUE),
(4, 'hammer', 'tools', 42, TRUE),
(5, 'screwdriver', 'tools', 7, TRUE),
(6, 'drill', 'tools', 89, TRUE)
) AS items(id, item, category, price, in_stock)
""")
print(rel.sql_query())
Result
SELECT *
FROM (VALUES
(1, 'jeans', 'clothing', 20, TRUE),
(2, 't-shirt', 'clothing', 8, FALSE),
(3, 'jacket', 'clothing', 65, TRUE),
(4, 'hammer', 'tools', 42, TRUE),
(5, 'screwdriver', 'tools', 7, TRUE),
(6, 'drill', 'tools', 89, TRUE)
) AS items(id, item, category, price, in_stock)
type
Get the type of the relation.
Example
import duckdb
duckdb_conn = duckdb.connect()
rel = duckdb_conn.sql("""
SELECT *
FROM (VALUES
(1, 'jeans', 'clothing', 20, TRUE),
(2, 't-shirt', 'clothing', 8, FALSE),
(3, 'jacket', 'clothing', 65, TRUE),
(4, 'hammer', 'tools', 42, TRUE),
(5, 'screwdriver', 'tools', 7, TRUE),
(6, 'drill', 'tools', 89, TRUE)
) AS items(id, item, category, price, in_stock)
""")
rel.type
Result
'QUERY_RELATION'
types
Return a list containing the types of the columns of the relation.
Aliases: dtypes
Example
import duckdb
duckdb_conn = duckdb.connect()
rel = duckdb_conn.sql("""
SELECT *
FROM (VALUES
(1, 'jeans', 'clothing', 20, TRUE),
(2, 't-shirt', 'clothing', 8, FALSE),
(3, 'jacket', 'clothing', 65, TRUE),
(4, 'hammer', 'tools', 42, TRUE),
(5, 'screwdriver', 'tools', 7, TRUE),
(6, 'drill', 'tools', 89, TRUE)
) AS items(id, item, category, price, in_stock)
""")
rel.types
Result
[INTEGER, VARCHAR, VARCHAR, INTEGER, BOOLEAN]
Transformation
This section contains the methods which can be used to chain queries. They build a new query from the relation and run nothing.
| Name | Description |
|---|---|
aggregate |
Compute the aggregate aggr_expr by the optional groups group_expr on the relation. |
apply |
Compute the function of a single column or a list of columns by the optional groups on the relation. |
cross |
Create cross/cartesian product of two relational objects. |
distinct |
Retrieve distinct rows from this relation object, or the first row of each distinct value of on. |
drop |
Remove columns. |
except_ |
Create the set except of this relation object with another relation object in other_rel. |
filter |
Filter the relation object by the filter in filter_expr. |
group_by |
Begin a grouped aggregation; continue with .agg(...). |
head |
The first n rows. |
intersect |
Create the set intersection of this relation object with another relation object in other_rel. |
join |
Join the relation object with another relation object in other_rel. |
limit |
Only retrieve the first n rows from this relation object, starting at offset. |
map |
Calls the passed function on the relation. |
offset |
Skip n rows. |
order |
Reorder the relation object by order_expr, which is SQL order text or an expression. |
pivot |
Turn the given values of column into columns holding aggregate; the values are explicit. |
project |
Alias of select(). |
rename |
Rename columns, given as old=new. |
sample |
A random subset: n rows, or percent of them, with seed repeating a draw. |
select |
Project the relation object by the projection in project_expr. |
select_dtypes |
Alias of select_types(). |
select_types |
Select columns from the relation, by filtering based on type(s). |
sort |
Reorder the relation object by the provided expressions. |
union |
Create the set union of this relation object with another relation object in other_rel. |
union_by_name |
Rows from both relations, matching columns by name; keeps duplicates unless all is false. |
unnest |
Expand list columns to one row per element. |
unpivot |
Turn the named columns into rows; name and value name the two new columns. |
with_columns |
Add columns, replacing any of the same name in place. |
aggregate
aggregate(self, aggr_expr: object, group_expr: object = '') -> DuckDBPyRelation
Compute the aggregate aggr_expr by the optional groups group_expr on the relation.
Parameters
-
aggr_expr : str, list[Expression]
The columns and aggregates to compute: SQL text, or a list of Expressions, in which a string is a column name.
-
group_expr : str, Expression, None, default: ''
The columns to group by, as SQL text or an Expression.
''orNonegroups by every column ofaggr_exprthat is not an aggregate (GROUP BY ALL).
Example
import duckdb
duckdb_conn = duckdb.connect()
rel = duckdb_conn.sql("""
SELECT *
FROM (VALUES
(1, 'jeans', 'clothing', 20, TRUE),
(2, 't-shirt', 'clothing', 8, FALSE),
(3, 'jacket', 'clothing', 65, TRUE),
(4, 'hammer', 'tools', 42, TRUE),
(5, 'screwdriver', 'tools', 7, TRUE),
(6, 'drill', 'tools', 89, TRUE)
) AS items(id, item, category, price, in_stock)
""")
rel.aggregate("category, max(price) AS max_price").order("category")
Result
┌──────────┬───────────┐
│ category │ max_price │
│ varchar │ int32 │
├──────────┼───────────┤
│ clothing │ 65 │
│ tools │ 89 │
└──────────┴───────────┘
apply
apply(self, function_name: str, function_aggr: str, group_expr: str = '', function_parameter: str = '', projected_columns: str = '') -> DuckDBPyRelation
Compute the function of a single column or a list of columns by the optional groups on the relation.
Parameters
-
function_name : str
Name of the function to apply over the relation.
-
function_aggr : str
The list of columns to apply the function over.
-
group_expr : str, default: ''
Optional SQL expression for grouping.
-
function_parameter : str, default: ''
Optional parameters to pass into the function.
-
projected_columns : str, default: ''
Comma-separated list of columns to include in the result.
Example
import duckdb
duckdb_conn = duckdb.connect()
rel = duckdb_conn.sql("""
SELECT *
FROM (VALUES
(1, 'jeans', 'clothing', 20, TRUE),
(2, 't-shirt', 'clothing', 8, FALSE),
(3, 'jacket', 'clothing', 65, TRUE),
(4, 'hammer', 'tools', 42, TRUE),
(5, 'screwdriver', 'tools', 7, TRUE),
(6, 'drill', 'tools', 89, TRUE)
) AS items(id, item, category, price, in_stock)
""")
rel.apply("max", "price", group_expr="category", projected_columns="category").order("category")
Result
┌──────────┬────────────┐
│ category │ max(price) │
│ varchar │ int32 │
├──────────┼────────────┤
│ clothing │ 65 │
│ tools │ 89 │
└──────────┴────────────┘
cross
cross(self, other_rel: DuckDBPyRelation) -> DuckDBPyRelation
Create cross/cartesian product of two relational objects.
Parameters
-
other_rel : DuckDBPyRelation
Another relation to perform a cross product with.
Example
import duckdb
duckdb_conn = duckdb.connect()
rel = duckdb_conn.sql("""
SELECT *
FROM (VALUES
(1, 'jeans', 'clothing', 20, TRUE),
(2, 't-shirt', 'clothing', 8, FALSE),
(3, 'jacket', 'clothing', 65, TRUE),
(4, 'hammer', 'tools', 42, TRUE),
(5, 'screwdriver', 'tools', 7, TRUE),
(6, 'drill', 'tools', 89, TRUE)
) AS items(id, item, category, price, in_stock)
""")
sizes = duckdb_conn.sql("SELECT * FROM (VALUES ('S'), ('M')) AS sizes(size)")
rel.filter("category = 'clothing'").select("item").cross(sizes).order("item, size")
Result
┌─────────┬─────────┐
│ item │ size │
│ varchar │ varchar │
├─────────┼─────────┤
│ jacket │ M │
│ jacket │ S │
│ jeans │ M │
│ jeans │ S │
│ t-shirt │ M │
│ t-shirt │ S │
└─────────┴─────────┘
distinct
distinct(self, on: object = None) -> DuckDBPyRelation
Retrieve distinct rows from this relation object, or the first row of each distinct value of on.
Parameters
-
on : str, Expression, list, default: None
A column name, an Expression or a list of them: keep one row for each distinct value of these columns, as SQL
DISTINCT ONdoes. Omitted, only fully duplicate rows are removed.
Example
import duckdb
duckdb_conn = duckdb.connect()
rel = duckdb_conn.sql("""
SELECT *
FROM (VALUES
(1, 'jeans', 'clothing', 20, TRUE),
(2, 't-shirt', 'clothing', 8, FALSE),
(3, 'jacket', 'clothing', 65, TRUE),
(4, 'hammer', 'tools', 42, TRUE),
(5, 'screwdriver', 'tools', 7, TRUE),
(6, 'drill', 'tools', 89, TRUE)
) AS items(id, item, category, price, in_stock)
""")
rel.select("category").distinct().order("category")
Result
┌──────────┐
│ category │
│ varchar │
├──────────┤
│ clothing │
│ tools │
└──────────┘
drop
drop(self, *columns: str) -> DuckDBPyRelation
Remove columns.
Parameters
-
*columns : str
Names of the columns to remove; a name the relation does not have raises
BinderException.
Example
import duckdb
duckdb_conn = duckdb.connect()
rel = duckdb_conn.sql("""
SELECT *
FROM (VALUES
(1, 'jeans', 'clothing', 20, TRUE),
(2, 't-shirt', 'clothing', 8, FALSE),
(3, 'jacket', 'clothing', 65, TRUE),
(4, 'hammer', 'tools', 42, TRUE),
(5, 'screwdriver', 'tools', 7, TRUE),
(6, 'drill', 'tools', 89, TRUE)
) AS items(id, item, category, price, in_stock)
""")
rel.drop("id", "in_stock")
Result
┌─────────────┬──────────┬───────┐
│ item │ category │ price │
│ varchar │ varchar │ int32 │
├─────────────┼──────────┼───────┤
│ jeans │ clothing │ 20 │
│ t-shirt │ clothing │ 8 │
│ jacket │ clothing │ 65 │
│ hammer │ tools │ 42 │
│ screwdriver │ tools │ 7 │
│ drill │ tools │ 89 │
└─────────────┴──────────┴───────┘
except_
except_(self, other_rel: DuckDBPyRelation) -> DuckDBPyRelation
Create the set except of this relation object with another relation object in other_rel.
The difference is EXCEPT ALL, so duplicates count: a row that appears three times in this relation and once in other_rel appears twice in the result.
Parameters
-
other_rel : DuckDBPyRelation
The relation to combine with this one; it must have the same number of columns.
Example
import duckdb
duckdb_conn = duckdb.connect()
rel = duckdb_conn.sql("""
SELECT *
FROM (VALUES
(1, 'jeans', 'clothing', 20, TRUE),
(2, 't-shirt', 'clothing', 8, FALSE),
(3, 'jacket', 'clothing', 65, TRUE),
(4, 'hammer', 'tools', 42, TRUE),
(5, 'screwdriver', 'tools', 7, TRUE),
(6, 'drill', 'tools', 89, TRUE)
) AS items(id, item, category, price, in_stock)
""")
categories = rel.select("category")
expensive = rel.filter("price > 30").select("category")
categories.except_(expensive).order("category")
Result
┌──────────┐
│ category │
│ varchar │
├──────────┤
│ clothing │
│ clothing │
│ tools │
└──────────┘
filter
filter(self, filter_expr: object) -> DuckDBPyRelation
Filter the relation object by the filter in filter_expr.
Parameters
-
filter_expr : str, Expression
The filter expression to apply over the relation.
Example
import duckdb
duckdb_conn = duckdb.connect()
rel = duckdb_conn.sql("""
SELECT *
FROM (VALUES
(1, 'jeans', 'clothing', 20, TRUE),
(2, 't-shirt', 'clothing', 8, FALSE),
(3, 'jacket', 'clothing', 65, TRUE),
(4, 'hammer', 'tools', 42, TRUE),
(5, 'screwdriver', 'tools', 7, TRUE),
(6, 'drill', 'tools', 89, TRUE)
) AS items(id, item, category, price, in_stock)
""")
rel.filter("price > 30")
Result
┌───────┬─────────┬──────────┬───────┬──────────┐
│ id │ item │ category │ price │ in_stock │
│ int32 │ varchar │ varchar │ int32 │ boolean │
├───────┼─────────┼──────────┼───────┼──────────┤
│ 3 │ jacket │ clothing │ 65 │ true │
│ 4 │ hammer │ tools │ 42 │ true │
│ 6 │ drill │ tools │ 89 │ true │
└───────┴─────────┴──────────┴───────┴──────────┘
group_by
group_by(self, *columns: object) -> GroupedRelation
Begin a grouped aggregation; continue with .agg(...).
group_by() returns a grouped relation whose only method is agg(*aggregates). agg() reads its arguments as aggregate() reads aggr_expr: one string is SQL text, which may list several aggregates; among several arguments, a string is a column name and an Expression is an aggregate. It returns a relation whose first columns are the group columns.
Parameters
-
*columns : str, Expression
The columns to group by: column names or Expressions.
Example
import duckdb
duckdb_conn = duckdb.connect()
rel = duckdb_conn.sql("""
SELECT *
FROM (VALUES
(1, 'jeans', 'clothing', 20, TRUE),
(2, 't-shirt', 'clothing', 8, FALSE),
(3, 'jacket', 'clothing', 65, TRUE),
(4, 'hammer', 'tools', 42, TRUE),
(5, 'screwdriver', 'tools', 7, TRUE),
(6, 'drill', 'tools', 89, TRUE)
) AS items(id, item, category, price, in_stock)
""")
rel.group_by("category").agg("sum(price) AS total, count(*) AS n").order("category")
Result
┌──────────┬────────┬───────┐
│ category │ total │ n │
│ varchar │ int128 │ int64 │
├──────────┼────────┼───────┤
│ clothing │ 93 │ 3 │
│ tools │ 138 │ 3 │
└──────────┴────────┴───────┘
head
head(self, n: int = 5) -> DuckDBPyRelation
The first n rows.
Parameters
-
n : int, default: 5
The number of rows to keep.
Example
import duckdb
duckdb_conn = duckdb.connect()
rel = duckdb_conn.sql("""
SELECT *
FROM (VALUES
(1, 'jeans', 'clothing', 20, TRUE),
(2, 't-shirt', 'clothing', 8, FALSE),
(3, 'jacket', 'clothing', 65, TRUE),
(4, 'hammer', 'tools', 42, TRUE),
(5, 'screwdriver', 'tools', 7, TRUE),
(6, 'drill', 'tools', 89, TRUE)
) AS items(id, item, category, price, in_stock)
""")
rel.head(3)
Result
┌───────┬─────────┬──────────┬───────┬──────────┐
│ id │ item │ category │ price │ in_stock │
│ int32 │ varchar │ varchar │ int32 │ boolean │
├───────┼─────────┼──────────┼───────┼──────────┤
│ 1 │ jeans │ clothing │ 20 │ true │
│ 2 │ t-shirt │ clothing │ 8 │ false │
│ 3 │ jacket │ clothing │ 65 │ true │
└───────┴─────────┴──────────┴───────┴──────────┘
intersect
intersect(self, other_rel: DuckDBPyRelation) -> DuckDBPyRelation
Create the set intersection of this relation object with another relation object in other_rel.
The intersection is INTERSECT ALL, so duplicates count: a row that appears three times in this relation and twice in other_rel appears twice in the result.
Parameters
-
other_rel : DuckDBPyRelation
The relation to combine with this one; it must have the same number of columns.
Example
import duckdb
duckdb_conn = duckdb.connect()
rel = duckdb_conn.sql("""
SELECT *
FROM (VALUES
(1, 'jeans', 'clothing', 20, TRUE),
(2, 't-shirt', 'clothing', 8, FALSE),
(3, 'jacket', 'clothing', 65, TRUE),
(4, 'hammer', 'tools', 42, TRUE),
(5, 'screwdriver', 'tools', 7, TRUE),
(6, 'drill', 'tools', 89, TRUE)
) AS items(id, item, category, price, in_stock)
""")
categories = rel.select("category")
expensive = rel.filter("price > 30").select("category")
categories.intersect(expensive).order("category")
Result
┌──────────┐
│ category │
│ varchar │
├──────────┤
│ clothing │
│ tools │
│ tools │
└──────────┘
join
join(self, other_rel: object, condition: object = None, how: str = 'inner', suffix: str | None = None) -> DuckDBPyRelation
Join the relation object with another relation object in other_rel.
The condition is SQL text, a column name or a list of them for a USING join, an Expression, or a function of the two sides. Types supported are 'inner', 'left', 'right', 'outer', 'full', 'semi', 'anti', 'cross', 'positional', 'natural' and 'asof'. With suffix, a column of the right side whose name the left side already has is renamed with the suffix appended.
An 'inner', 'left', 'right', 'outer', 'full', 'semi', 'anti' or 'asof' join needs a condition, and raises InvalidInputException without one; a 'cross', 'positional' or 'natural' join takes none. The joins section of the FROM clause says what each join type does. A CROSS join is also provided through the cross() method.
Parameters
-
other_rel : DuckDBPyRelation
The relation to join with the current relation.
-
condition : str, list[str], Expression, Callable, default: None
The join condition: SQL text such as
'a.id = b.id', a column name or a list of column names for aUSINGjoin, an Expression or a function that takes the two sides and returns an Expression, whereside['id']is the columnidof that side. -
how : str, default: 'inner'
The type of join:
'inner','left','right','outer','full','semi','anti','cross','positional','natural'or'asof'. -
suffix : str, default: None
Rename each column of the right side whose name the left side also has, by appending the suffix; the columns of a
USINGor natural join, which appear once, keep their names.
Example
import duckdb
duckdb_conn = duckdb.connect()
left = duckdb_conn.sql("SELECT * FROM (VALUES (1, 'a'), (2, 'b'), (3, 'c')) AS t(id, name)")
right = duckdb_conn.sql("SELECT * FROM (VALUES (1, 'x'), (3, 'z'), (4, 'w')) AS t(id, name)")
print(left.join(right, "id").order("id"))
left.join(right, lambda a, b: a["id"] == b["id"], how="left", suffix="_right").order("id")
Result
┌───────┬─────────┬─────────┐
│ id │ name │ name │
│ int32 │ varchar │ varchar │
├───────┼─────────┼─────────┤
│ 1 │ a │ x │
│ 3 │ c │ z │
└───────┴─────────┴─────────┘
┌───────┬─────────┬──────────┬────────────┐
│ id │ name │ id_right │ name_right │
│ int32 │ varchar │ int32 │ varchar │
├───────┼─────────┼──────────┼────────────┤
│ 1 │ a │ 1 │ x │
│ 2 │ b │ NULL │ NULL │
│ 3 │ c │ 3 │ z │
└───────┴─────────┴──────────┴────────────┘
limit
limit(self, n: int, offset: int = 0) -> DuckDBPyRelation
Only retrieve the first n rows from this relation object, starting at offset.
To read the first rows into Python, as fetchone() and fetchmany() did on a relation before DuckDB 2.0, use rel.limit(1).fetchall() and rel.limit(n).fetchall(). To read all the rows a batch at a time, use iter_rows().
Parameters
-
n : int
The maximum number of rows to return.
-
offset : int, default: 0
The number of rows to skip before starting to return rows.
Example
import duckdb
duckdb_conn = duckdb.connect()
rel = duckdb_conn.sql("""
SELECT *
FROM (VALUES
(1, 'jeans', 'clothing', 20, TRUE),
(2, 't-shirt', 'clothing', 8, FALSE),
(3, 'jacket', 'clothing', 65, TRUE),
(4, 'hammer', 'tools', 42, TRUE),
(5, 'screwdriver', 'tools', 7, TRUE),
(6, 'drill', 'tools', 89, TRUE)
) AS items(id, item, category, price, in_stock)
""")
rel.limit(1)
Result
┌───────┬─────────┬──────────┬───────┬──────────┐
│ id │ item │ category │ price │ in_stock │
│ int32 │ varchar │ varchar │ int32 │ boolean │
├───────┼─────────┼──────────┼───────┼──────────┤
│ 1 │ jeans │ clothing │ 20 │ true │
└───────┴─────────┴──────────┴───────┴──────────┘
map
map(self, map_function: Callable[..., Any], *, schema: object = None) -> DuckDBPyRelation
Calls the passed function on the relation.
Parameters
-
map_function : Callable
A Python function that takes a DataFrame and returns a transformed DataFrame.
-
schema : dict, keyword-only, default: None
The columns of the output relation, as a dict of name to type. Without it, the function is called once on an empty DataFrame when the relation is built, to learn the columns it returns.
Example
import duckdb
from pandas import DataFrame
def multiply_by_2(df: DataFrame):
df["id"] = df["id"] * 2
return df
duckdb_conn = duckdb.connect()
rel = duckdb_conn.sql("SELECT range AS id, 'dummy' AS text FROM range(1, 3)")
rel.map(multiply_by_2, schema={"id": int, "text": str})
Result
┌───────┬─────────┐
│ id │ text │
│ int64 │ varchar │
├───────┼─────────┤
│ 2 │ dummy │
│ 4 │ dummy │
└───────┴─────────┘
offset
offset(self, n: int) -> DuckDBPyRelation
Skip n rows.
Parameters
-
n : int
The number of rows to skip.
Example
import duckdb
duckdb_conn = duckdb.connect()
rel = duckdb_conn.sql("""
SELECT *
FROM (VALUES
(1, 'jeans', 'clothing', 20, TRUE),
(2, 't-shirt', 'clothing', 8, FALSE),
(3, 'jacket', 'clothing', 65, TRUE),
(4, 'hammer', 'tools', 42, TRUE),
(5, 'screwdriver', 'tools', 7, TRUE),
(6, 'drill', 'tools', 89, TRUE)
) AS items(id, item, category, price, in_stock)
""")
rel.order("id").offset(4)
Result
┌───────┬─────────────┬──────────┬───────┬──────────┐
│ id │ item │ category │ price │ in_stock │
│ int32 │ varchar │ varchar │ int32 │ boolean │
├───────┼─────────────┼──────────┼───────┼──────────┤
│ 5 │ screwdriver │ tools │ 7 │ true │
│ 6 │ drill │ tools │ 89 │ true │
└───────┴─────────────┴──────────┴───────┴──────────┘
order
order(self, order_expr: object) -> DuckDBPyRelation
Reorder the relation object by order_expr, which is SQL order text or an expression.
Parameters
-
order_expr : str, Expression
The ordering of the rows: SQL text such as
'price DESC', or an Expression such ascol('price').desc().
Example
import duckdb
duckdb_conn = duckdb.connect()
rel = duckdb_conn.sql("""
SELECT *
FROM (VALUES
(1, 'jeans', 'clothing', 20, TRUE),
(2, 't-shirt', 'clothing', 8, FALSE),
(3, 'jacket', 'clothing', 65, TRUE),
(4, 'hammer', 'tools', 42, TRUE),
(5, 'screwdriver', 'tools', 7, TRUE),
(6, 'drill', 'tools', 89, TRUE)
) AS items(id, item, category, price, in_stock)
""")
rel.order("price DESC")
Result
┌───────┬─────────────┬──────────┬───────┬──────────┐
│ id │ item │ category │ price │ in_stock │
│ int32 │ varchar │ varchar │ int32 │ boolean │
├───────┼─────────────┼──────────┼───────┼──────────┤
│ 6 │ drill │ tools │ 89 │ true │
│ 3 │ jacket │ clothing │ 65 │ true │
│ 4 │ hammer │ tools │ 42 │ true │
│ 1 │ jeans │ clothing │ 20 │ true │
│ 2 │ t-shirt │ clothing │ 8 │ false │
│ 5 │ screwdriver │ tools │ 7 │ true │
└───────┴─────────────┴──────────┴───────┴──────────┘
pivot
pivot(self, column: object, values: Iterable[object], aggregate: object) -> DuckDBPyRelation
Turn the given values of column into columns holding aggregate; the values are explicit.
It runs a PIVOT with the values given; the columns not named in column or aggregate are the rows of the result.
Parameters
-
column : str, Expression
The column whose values become the new columns.
-
values : Iterable
The values of
columnthat become columns, as Python values. -
aggregate : str, Expression
The aggregate each new column holds, as SQL text or an Expression.
Example
import duckdb
duckdb_conn = duckdb.connect()
rel = duckdb_conn.sql("""
SELECT *
FROM (VALUES
(1, 'jeans', 'clothing', 20, TRUE),
(2, 't-shirt', 'clothing', 8, FALSE),
(3, 'jacket', 'clothing', 65, TRUE),
(4, 'hammer', 'tools', 42, TRUE),
(5, 'screwdriver', 'tools', 7, TRUE),
(6, 'drill', 'tools', 89, TRUE)
) AS items(id, item, category, price, in_stock)
""")
rel.select("in_stock, category, price").pivot("category", ["clothing", "tools"], "sum(price)").order("in_stock")
Result
┌──────────┬──────────┬────────┐
│ in_stock │ clothing │ tools │
│ boolean │ int128 │ int128 │
├──────────┼──────────┼────────┤
│ false │ 8 │ NULL │
│ true │ 85 │ 138 │
└──────────┴──────────┴────────┘
project
project(self, *args: object, groups: str = '') -> DuckDBPyRelation
Alias of select().
rename
rename(self, **columns: str) -> DuckDBPyRelation
Rename columns, given as old=new.
Parameters
-
**columns : str
The columns to rename, as
old=new; a name the relation does not have raisesBinderException.
Example
import duckdb
duckdb_conn = duckdb.connect()
rel = duckdb_conn.sql("""
SELECT *
FROM (VALUES
(1, 'jeans', 'clothing', 20, TRUE),
(2, 't-shirt', 'clothing', 8, FALSE),
(3, 'jacket', 'clothing', 65, TRUE),
(4, 'hammer', 'tools', 42, TRUE),
(5, 'screwdriver', 'tools', 7, TRUE),
(6, 'drill', 'tools', 89, TRUE)
) AS items(id, item, category, price, in_stock)
""")
rel.rename(price="unit_price")
Result
┌───────┬─────────────┬──────────┬────────────┬──────────┐
│ id │ item │ category │ unit_price │ in_stock │
│ int32 │ varchar │ varchar │ int32 │ boolean │
├───────┼─────────────┼──────────┼────────────┼──────────┤
│ 1 │ jeans │ clothing │ 20 │ true │
│ 2 │ t-shirt │ clothing │ 8 │ false │
│ 3 │ jacket │ clothing │ 65 │ true │
│ 4 │ hammer │ tools │ 42 │ true │
│ 5 │ screwdriver │ tools │ 7 │ true │
│ 6 │ drill │ tools │ 89 │ true │
└───────┴─────────────┴──────────┴────────────┴──────────┘
sample
sample(self, n: int | None = None, *, percent: float | None = None, seed: int | None = None, method: str | None = None) -> DuckDBPyRelation
A random subset: n rows, or percent of them, with seed repeating a draw.
See Samples for the sampling methods. A fixed seed gives the same sample on every run only when DuckDB runs on one thread.
Parameters
-
n : int, default: None
The number of rows to draw; give either
norpercent. -
percent : float, keyword-only, default: None
The percentage of the rows to draw.
-
seed : int, keyword-only, default: None
The seed of the random draw.
-
method : str, keyword-only, default: None
'reservoir','bernoulli'or'system';'reservoir'fornand'bernoulli'forpercentwhen omitted.
Example
import duckdb
duckdb_conn = duckdb.connect()
rel = duckdb_conn.sql("""
SELECT *
FROM (VALUES
(1, 'jeans', 'clothing', 20, TRUE),
(2, 't-shirt', 'clothing', 8, FALSE),
(3, 'jacket', 'clothing', 65, TRUE),
(4, 'hammer', 'tools', 42, TRUE),
(5, 'screwdriver', 'tools', 7, TRUE),
(6, 'drill', 'tools', 89, TRUE)
) AS items(id, item, category, price, in_stock)
""")
duckdb_conn.sql("SET threads = 1")
rel.sample(3, seed=42).order("id")
Result
┌───────┬─────────┬──────────┬───────┬──────────┐
│ id │ item │ category │ price │ in_stock │
│ int32 │ varchar │ varchar │ int32 │ boolean │
├───────┼─────────┼──────────┼───────┼──────────┤
│ 3 │ jacket │ clothing │ 65 │ true │
│ 4 │ hammer │ tools │ 42 │ true │
│ 6 │ drill │ tools │ 89 │ true │
└───────┴─────────┴──────────┴───────┴──────────┘
select
select(self, *args: object, groups: str = '') -> DuckDBPyRelation
Project the relation object by the projection in project_expr.
Aliases: project
Parameters
-
*args : str, Expression
The columns to keep, as strings or Expressions. A single string is SQL text, which may list several columns or expressions; among several arguments, each string names one column.
-
groups : str, keyword-only, default: ''
Comma-separated list of columns to include in the
GROUP BY.
Example
import duckdb
duckdb_conn = duckdb.connect()
rel = duckdb_conn.sql("""
SELECT *
FROM (VALUES
(1, 'jeans', 'clothing', 20, TRUE),
(2, 't-shirt', 'clothing', 8, FALSE),
(3, 'jacket', 'clothing', 65, TRUE),
(4, 'hammer', 'tools', 42, TRUE),
(5, 'screwdriver', 'tools', 7, TRUE),
(6, 'drill', 'tools', 89, TRUE)
) AS items(id, item, category, price, in_stock)
""")
rel.select("item, price")
Result
┌─────────────┬───────┐
│ item │ price │
│ varchar │ int32 │
├─────────────┼───────┤
│ jeans │ 20 │
│ t-shirt │ 8 │
│ jacket │ 65 │
│ hammer │ 42 │
│ screwdriver │ 7 │
│ drill │ 89 │
└─────────────┴───────┘
select_dtypes
select_dtypes(self, types: object) -> DuckDBPyRelation
Alias of select_types().
select_types
select_types(self, types: object) -> DuckDBPyRelation
Select columns from the relation, by filtering based on type(s).
Aliases: select_dtypes
Parameters
-
types : list
The types of the columns to keep, as a list of
DuckDBPyTypevalues or type names such as'VARCHAR'.
Example
import duckdb
duckdb_conn = duckdb.connect()
rel = duckdb_conn.sql("""
SELECT *
FROM (VALUES
(1, 'jeans', 'clothing', 20, TRUE),
(2, 't-shirt', 'clothing', 8, FALSE),
(3, 'jacket', 'clothing', 65, TRUE),
(4, 'hammer', 'tools', 42, TRUE),
(5, 'screwdriver', 'tools', 7, TRUE),
(6, 'drill', 'tools', 89, TRUE)
) AS items(id, item, category, price, in_stock)
""")
rel.select_types([duckdb.sqltypes.VARCHAR])
Result
┌─────────────┬──────────┐
│ item │ category │
│ varchar │ varchar │
├─────────────┼──────────┤
│ jeans │ clothing │
│ t-shirt │ clothing │
│ jacket │ clothing │
│ hammer │ tools │
│ screwdriver │ tools │
│ drill │ tools │
└─────────────┴──────────┘
sort
sort(self, *args: object) -> DuckDBPyRelation
Reorder the relation object by the provided expressions.
Parameters
-
*args : str, Expression
The expressions to sort by, as SQL text such as
'price DESC'or as Expressions.
Example
import duckdb
duckdb_conn = duckdb.connect()
rel = duckdb_conn.sql("""
SELECT *
FROM (VALUES
(1, 'jeans', 'clothing', 20, TRUE),
(2, 't-shirt', 'clothing', 8, FALSE),
(3, 'jacket', 'clothing', 65, TRUE),
(4, 'hammer', 'tools', 42, TRUE),
(5, 'screwdriver', 'tools', 7, TRUE),
(6, 'drill', 'tools', 89, TRUE)
) AS items(id, item, category, price, in_stock)
""")
rel.sort("category", "price DESC")
Result
┌───────┬─────────────┬──────────┬───────┬──────────┐
│ id │ item │ category │ price │ in_stock │
│ int32 │ varchar │ varchar │ int32 │ boolean │
├───────┼─────────────┼──────────┼───────┼──────────┤
│ 3 │ jacket │ clothing │ 65 │ true │
│ 1 │ jeans │ clothing │ 20 │ true │
│ 2 │ t-shirt │ clothing │ 8 │ false │
│ 6 │ drill │ tools │ 89 │ true │
│ 4 │ hammer │ tools │ 42 │ true │
│ 5 │ screwdriver │ tools │ 7 │ true │
└───────┴─────────────┴──────────┴───────┴──────────┘
union
union(self, union_rel: DuckDBPyRelation) -> DuckDBPyRelation
Create the set union of this relation object with another relation object in other_rel.
The union is UNION ALL, so it keeps duplicate rows. To keep only distinct rows, apply distinct().
Parameters
-
union_rel : DuckDBPyRelation
The relation to combine with this one; it must have the same number of columns.
Example
import duckdb
duckdb_conn = duckdb.connect()
rel = duckdb_conn.sql("""
SELECT *
FROM (VALUES
(1, 'jeans', 'clothing', 20, TRUE),
(2, 't-shirt', 'clothing', 8, FALSE),
(3, 'jacket', 'clothing', 65, TRUE),
(4, 'hammer', 'tools', 42, TRUE),
(5, 'screwdriver', 'tools', 7, TRUE),
(6, 'drill', 'tools', 89, TRUE)
) AS items(id, item, category, price, in_stock)
""")
rel.union(rel).count("*")
Result
┌──────────────┐
│ count_star() │
│ int64 │
├──────────────┤
│ 12 │
└──────────────┘
union_by_name
union_by_name(self, other: DuckDBPyRelation, *, all: bool = True) -> DuckDBPyRelation
Rows from both relations, matching columns by name; keeps duplicates unless all is false.
Parameters
-
other : DuckDBPyRelation
The relation to combine with this one; a column that only one of them has is
NULLin the rows of the other. -
all : bool, keyword-only, default: True
Keep duplicate rows (
UNION ALL BY NAME); withFalse, keep only distinct rows (UNION BY NAME).
Example
import duckdb
duckdb_conn = duckdb.connect()
first = duckdb_conn.sql("SELECT 1 AS id, 10 AS x")
second = duckdb_conn.sql("SELECT 20 AS y, 2 AS id")
first.union_by_name(second).order("id")
Result
┌───────┬───────┬───────┐
│ id │ x │ y │
│ int32 │ int32 │ int32 │
├───────┼───────┼───────┤
│ 1 │ 10 │ NULL │
│ 2 │ NULL │ 20 │
└───────┴───────┴───────┘
unnest
unnest(self, *columns: str) -> DuckDBPyRelation
Expand list columns to one row per element.
Parameters
-
*columns : str
Names of the list columns to expand; each keeps its name and holds one element per row.
Example
import duckdb
duckdb_conn = duckdb.connect()
rel = duckdb_conn.sql("SELECT 1 AS id, [10, 20] AS amounts UNION ALL SELECT 2, [30]")
rel.unnest("amounts").order("id, amounts")
Result
┌───────┬─────────┐
│ id │ amounts │
│ int32 │ int32 │
├───────┼─────────┤
│ 1 │ 10 │
│ 1 │ 20 │
│ 2 │ 30 │
└───────┴─────────┘
unpivot
unpivot(self, *columns: str, name: str = 'name', value: str = 'value') -> DuckDBPyRelation
Turn the named columns into rows; name and value name the two new columns.
It runs an UNPIVOT; the columns not named stay as they are, repeated for each new row.
Parameters
-
*columns : str
Names of the columns to turn into rows.
-
name : str, keyword-only, default: 'name'
Name of the new column that holds the names of the unpivoted columns.
-
value : str, keyword-only, default: 'value'
Name of the new column that holds their values.
Example
import duckdb
duckdb_conn = duckdb.connect()
rel = duckdb_conn.sql("SELECT * FROM (VALUES ('north', 10, 20), ('south', 30, 40)) AS t(region, q1, q2)")
rel.unpivot("q1", "q2", name="quarter", value="amount").order("region, quarter")
Result
┌─────────┬─────────┬────────┐
│ region │ quarter │ amount │
│ varchar │ varchar │ int32 │
├─────────┼─────────┼────────┤
│ north │ q1 │ 10 │
│ north │ q2 │ 20 │
│ south │ q1 │ 30 │
│ south │ q2 │ 40 │
└─────────┴─────────┴────────┘
with_columns
with_columns(self, **columns: object) -> DuckDBPyRelation
Add columns, replacing any of the same name in place.
Parameters
-
**columns : Expression, object
The columns, as
name=value, where a value is an Expression, a column name or a Python value; a column of the same name is replaced in place, any other is added at the end.
Example
import duckdb
duckdb_conn = duckdb.connect()
rel = duckdb_conn.sql("""
SELECT *
FROM (VALUES
(1, 'jeans', 'clothing', 20, TRUE),
(2, 't-shirt', 'clothing', 8, FALSE),
(3, 'jacket', 'clothing', 65, TRUE),
(4, 'hammer', 'tools', 42, TRUE),
(5, 'screwdriver', 'tools', 7, TRUE),
(6, 'drill', 'tools', 89, TRUE)
) AS items(id, item, category, price, in_stock)
""")
from duckdb import col, lit
rel.with_columns(price=col("price") * 2, currency=lit("EUR"))
Result
┌───────┬─────────────┬──────────┬───────┬──────────┬──────────┐
│ id │ item │ category │ price │ in_stock │ currency │
│ int32 │ varchar │ varchar │ int32 │ boolean │ varchar │
├───────┼─────────────┼──────────┼───────┼──────────┼──────────┤
│ 1 │ jeans │ clothing │ 40 │ true │ EUR │
│ 2 │ t-shirt │ clothing │ 16 │ false │ EUR │
│ 3 │ jacket │ clothing │ 130 │ true │ EUR │
│ 4 │ hammer │ tools │ 84 │ true │ EUR │
│ 5 │ screwdriver │ tools │ 14 │ true │ EUR │
│ 6 │ drill │ tools │ 178 │ true │ EUR │
└───────┴─────────────┴──────────┴───────┴──────────┴──────────┘
Functions
This section contains the functions which can be applied to a relation, in order to get a (scalar) result. They build a new query and run nothing.
| Name | Description |
|---|---|
any_value |
Returns the first non-null value from a given expression. |
arg_max |
Finds the row with the maximum value for a value column and returns the value of that row for an argument column. |
arg_min |
Finds the row with the minimum value for a value column and returns the value of that row for an argument column. |
avg |
Computes the average of a given expression. |
bit_and |
Computes the bitwise AND of all bits present in a given expression. |
bit_or |
Computes the bitwise OR of all bits present in a given expression. |
bit_xor |
Computes the bitwise XOR of all bits present in a given expression. |
bitstring_agg |
Computes a bitstring with bits set for each distinct value in a given expression. |
bool_and |
Computes the logical AND of all values present in a given expression. |
bool_or |
Computes the logical OR of all values present in a given expression. |
count |
Computes the number of elements present in a given expression. |
cume_dist |
Computes the cumulative distribution within the partition. |
dense_rank |
Computes the dense rank within the partition. |
favg |
Computes the average of all values present in a given expression using a more accurate floating point summation (Kahan Sum). |
first |
Returns the first value of a given expression. |
first_value |
Computes the first value within the group or partition. |
fsum |
Computes the sum of all values present in a given expression using a more accurate floating point summation (Kahan Sum). |
geomean |
Computes the geometric mean over all values present in a given expression. |
histogram |
Computes the histogram over all values present in a given expression. |
lag |
Computes the lag within the partition. |
last |
Returns the last value of a given expression. |
last_value |
Computes the last value within the group or partition. |
lead |
Computes the lead within the partition. |
list |
Returns a list containing all values present in a given expression. |
max |
Returns the maximum value present in a given expression. |
mean |
Alias of avg(). |
median |
Computes the median over all values present in a given expression. |
min |
Returns the minimum value present in a given expression. |
mode |
Computes the mode over all values present in a given expression. |
n_tile |
Divides the partition as equally as possible into num_buckets. |
nth_value |
Computes the nth value within the partition. |
percent_rank |
Computes the relative rank within the partition. |
product |
Returns the product of all values present in a given expression. |
quantile |
Alias of quantile_disc(). |
quantile_cont |
Computes the interpolated quantile value for a given expression. |
quantile_disc |
Computes the exact quantile value for a given expression. |
rank |
Computes the rank within the partition. |
rank_dense |
Alias of dense_rank(). |
row_number |
Computes the row number within the partition. |
std |
Alias of stddev_samp(). |
stddev |
Alias of stddev_samp(). |
stddev_pop |
Computes the population standard deviation for a given expression. |
stddev_samp |
Computes the sample standard deviation for a given expression. |
string_agg |
Concatenates the values present in a given expression with a separator. |
sum |
Computes the sum of all values present in a given expression. |
unique |
Returns the distinct values in a column. |
value_counts |
Computes the number of elements present in a given expression, also projecting the original expression. |
var |
Alias of var_samp(). |
var_pop |
Computes the population variance for a given expression. |
var_samp |
Computes the sample variance for a given expression. |
variance |
Alias of var_samp(). |
any_value
any_value(self, expression: str, groups: str = '', window_spec: str = '', projected_columns: str = '') -> DuckDBPyRelation
Returns the first non-null value from a given expression.
Parameters
-
expression : str
The column or expression from which to retrieve any value.
-
groups : str, default: ''
Comma-separated list of columns to include in the
GROUP BY; cannot be combined withwindow_spec. -
window_spec : str, default: ''
Window specification, written as
OVER (PARTITION BY ... ORDER BY ...); cannot be combined withgroups. -
projected_columns : str, default: ''
Comma-separated list of columns to include in the result.
Example
import duckdb
duckdb_conn = duckdb.connect()
rel = duckdb_conn.sql("""
SELECT *
FROM (VALUES
(1, 'jeans', 'clothing', 20, TRUE),
(2, 't-shirt', 'clothing', 8, FALSE),
(3, 'jacket', 'clothing', 65, TRUE),
(4, 'hammer', 'tools', 42, TRUE),
(5, 'screwdriver', 'tools', 7, TRUE),
(6, 'drill', 'tools', 89, TRUE)
) AS items(id, item, category, price, in_stock)
""")
rel.any_value("item")
Result
┌─────────────────┐
│ any_value(item) │
│ varchar │
├─────────────────┤
│ jeans │
└─────────────────┘
arg_max
arg_max(self, arg_column: str, value_column: str, groups: str = '', window_spec: str = '', projected_columns: str = '') -> DuckDBPyRelation
Finds the row with the maximum value for a value column and returns the value of that row for an argument column.
Parameters
-
arg_column : str
The column whose value is returned, taken from the row where
value_columnis largest. -
value_column : str
The column whose largest value picks the row.
-
groups : str, default: ''
Comma-separated list of columns to include in the
GROUP BY; cannot be combined withwindow_spec. -
window_spec : str, default: ''
Window specification, written as
OVER (PARTITION BY ... ORDER BY ...); cannot be combined withgroups. -
projected_columns : str, default: ''
Comma-separated list of columns to include in the result.
Example
import duckdb
duckdb_conn = duckdb.connect()
rel = duckdb_conn.sql("""
SELECT *
FROM (VALUES
(1, 'jeans', 'clothing', 20, TRUE),
(2, 't-shirt', 'clothing', 8, FALSE),
(3, 'jacket', 'clothing', 65, TRUE),
(4, 'hammer', 'tools', 42, TRUE),
(5, 'screwdriver', 'tools', 7, TRUE),
(6, 'drill', 'tools', 89, TRUE)
) AS items(id, item, category, price, in_stock)
""")
rel.arg_max("item", "price", groups="category", projected_columns="category").order("category")
Result
┌──────────┬──────────────────────┐
│ category │ arg_max(item, price) │
│ varchar │ varchar │
├──────────┼──────────────────────┤
│ clothing │ jacket │
│ tools │ drill │
└──────────┴──────────────────────┘
arg_min
arg_min(self, arg_column: str, value_column: str, groups: str = '', window_spec: str = '', projected_columns: str = '') -> DuckDBPyRelation
Finds the row with the minimum value for a value column and returns the value of that row for an argument column.
Parameters
-
arg_column : str
The column whose value is returned, taken from the row where
value_columnis smallest. -
value_column : str
The column whose smallest value picks the row.
-
groups : str, default: ''
Comma-separated list of columns to include in the
GROUP BY; cannot be combined withwindow_spec. -
window_spec : str, default: ''
Window specification, written as
OVER (PARTITION BY ... ORDER BY ...); cannot be combined withgroups. -
projected_columns : str, default: ''
Comma-separated list of columns to include in the result.
Example
import duckdb
duckdb_conn = duckdb.connect()
rel = duckdb_conn.sql("""
SELECT *
FROM (VALUES
(1, 'jeans', 'clothing', 20, TRUE),
(2, 't-shirt', 'clothing', 8, FALSE),
(3, 'jacket', 'clothing', 65, TRUE),
(4, 'hammer', 'tools', 42, TRUE),
(5, 'screwdriver', 'tools', 7, TRUE),
(6, 'drill', 'tools', 89, TRUE)
) AS items(id, item, category, price, in_stock)
""")
rel.arg_min("item", "price", groups="category", projected_columns="category").order("category")
Result
┌──────────┬──────────────────────┐
│ category │ arg_min(item, price) │
│ varchar │ varchar │
├──────────┼──────────────────────┤
│ clothing │ t-shirt │
│ tools │ screwdriver │
└──────────┴──────────────────────┘
avg
avg(self, expression: str, groups: str = '', window_spec: str = '', projected_columns: str = '') -> DuckDBPyRelation
Computes the average of a given expression.
Aliases: mean
Parameters
-
expression : str
The column or expression to calculate the average of.
-
groups : str, default: ''
Comma-separated list of columns to include in the
GROUP BY; cannot be combined withwindow_spec. -
window_spec : str, default: ''
Window specification, written as
OVER (PARTITION BY ... ORDER BY ...); cannot be combined withgroups. -
projected_columns : str, default: ''
Comma-separated list of columns to include in the result.
Example
import duckdb
duckdb_conn = duckdb.connect()
rel = duckdb_conn.sql("""
SELECT *
FROM (VALUES
(1, 'jeans', 'clothing', 20, TRUE),
(2, 't-shirt', 'clothing', 8, FALSE),
(3, 'jacket', 'clothing', 65, TRUE),
(4, 'hammer', 'tools', 42, TRUE),
(5, 'screwdriver', 'tools', 7, TRUE),
(6, 'drill', 'tools', 89, TRUE)
) AS items(id, item, category, price, in_stock)
""")
rel.avg("price")
Result
┌────────────┐
│ avg(price) │
│ double │
├────────────┤
│ 38.5 │
└────────────┘
bit_and
bit_and(self, expression: str, groups: str = '', window_spec: str = '', projected_columns: str = '') -> DuckDBPyRelation
Computes the bitwise AND of all bits present in a given expression.
Parameters
-
expression : str
The column or expression to perform the bitwise AND aggregation on.
-
groups : str, default: ''
Comma-separated list of columns to include in the
GROUP BY; cannot be combined withwindow_spec. -
window_spec : str, default: ''
Window specification, written as
OVER (PARTITION BY ... ORDER BY ...); cannot be combined withgroups. -
projected_columns : str, default: ''
Comma-separated list of columns to include in the result.
Example
import duckdb
duckdb_conn = duckdb.connect()
rel = duckdb_conn.sql("""
SELECT *
FROM (VALUES
(1, 'jeans', 'clothing', 20, TRUE),
(2, 't-shirt', 'clothing', 8, FALSE),
(3, 'jacket', 'clothing', 65, TRUE),
(4, 'hammer', 'tools', 42, TRUE),
(5, 'screwdriver', 'tools', 7, TRUE),
(6, 'drill', 'tools', 89, TRUE)
) AS items(id, item, category, price, in_stock)
""")
rel.bit_and("id", groups="category", projected_columns="category").order("category")
Result
┌──────────┬─────────────┐
│ category │ bit_and(id) │
│ varchar │ int32 │
├──────────┼─────────────┤
│ clothing │ 0 │
│ tools │ 4 │
└──────────┴─────────────┘
bit_or
bit_or(self, expression: str, groups: str = '', window_spec: str = '', projected_columns: str = '') -> DuckDBPyRelation
Computes the bitwise OR of all bits present in a given expression.
Parameters
-
expression : str
The column or expression to perform the bitwise OR aggregation on.
-
groups : str, default: ''
Comma-separated list of columns to include in the
GROUP BY; cannot be combined withwindow_spec. -
window_spec : str, default: ''
Window specification, written as
OVER (PARTITION BY ... ORDER BY ...); cannot be combined withgroups. -
projected_columns : str, default: ''
Comma-separated list of columns to include in the result.
Example
import duckdb
duckdb_conn = duckdb.connect()
rel = duckdb_conn.sql("""
SELECT *
FROM (VALUES
(1, 'jeans', 'clothing', 20, TRUE),
(2, 't-shirt', 'clothing', 8, FALSE),
(3, 'jacket', 'clothing', 65, TRUE),
(4, 'hammer', 'tools', 42, TRUE),
(5, 'screwdriver', 'tools', 7, TRUE),
(6, 'drill', 'tools', 89, TRUE)
) AS items(id, item, category, price, in_stock)
""")
rel.bit_or("id", groups="category", projected_columns="category").order("category")
Result
┌──────────┬────────────┐
│ category │ bit_or(id) │
│ varchar │ int32 │
├──────────┼────────────┤
│ clothing │ 3 │
│ tools │ 7 │
└──────────┴────────────┘
bit_xor
bit_xor(self, expression: str, groups: str = '', window_spec: str = '', projected_columns: str = '') -> DuckDBPyRelation
Computes the bitwise XOR of all bits present in a given expression.
Parameters
-
expression : str
The column or expression to perform the bitwise XOR aggregation on.
-
groups : str, default: ''
Comma-separated list of columns to include in the
GROUP BY; cannot be combined withwindow_spec. -
window_spec : str, default: ''
Window specification, written as
OVER (PARTITION BY ... ORDER BY ...); cannot be combined withgroups. -
projected_columns : str, default: ''
Comma-separated list of columns to include in the result.
Example
import duckdb
duckdb_conn = duckdb.connect()
rel = duckdb_conn.sql("""
SELECT *
FROM (VALUES
(1, 'jeans', 'clothing', 20, TRUE),
(2, 't-shirt', 'clothing', 8, FALSE),
(3, 'jacket', 'clothing', 65, TRUE),
(4, 'hammer', 'tools', 42, TRUE),
(5, 'screwdriver', 'tools', 7, TRUE),
(6, 'drill', 'tools', 89, TRUE)
) AS items(id, item, category, price, in_stock)
""")
rel.bit_xor("id", groups="category", projected_columns="category").order("category")
Result
┌──────────┬─────────────┐
│ category │ bit_xor(id) │
│ varchar │ int32 │
├──────────┼─────────────┤
│ clothing │ 0 │
│ tools │ 7 │
└──────────┴─────────────┘
bitstring_agg
bitstring_agg(self, expression: str, min: int | None = None, max: int | None = None, groups: str = '', window_spec: str = '', projected_columns: str = '') -> DuckDBPyRelation
Computes a bitstring with bits set for each distinct value in a given expression.
Parameters
-
expression : str
The column or expression to aggregate as a bitstring.
-
min : int, default: None
The smallest value the bitstring can hold; give both
minandmax, or neither. -
max : int, default: None
The largest value the bitstring can hold; give both
minandmax, or neither. -
groups : str, default: ''
Comma-separated list of columns to include in the
GROUP BY; cannot be combined withwindow_spec. -
window_spec : str, default: ''
Window specification, written as
OVER (PARTITION BY ... ORDER BY ...); cannot be combined withgroups. -
projected_columns : str, default: ''
Comma-separated list of columns to include in the result.
Example
import duckdb
duckdb_conn = duckdb.connect()
rel = duckdb_conn.sql("""
SELECT *
FROM (VALUES
(1, 'jeans', 'clothing', 20, TRUE),
(2, 't-shirt', 'clothing', 8, FALSE),
(3, 'jacket', 'clothing', 65, TRUE),
(4, 'hammer', 'tools', 42, TRUE),
(5, 'screwdriver', 'tools', 7, TRUE),
(6, 'drill', 'tools', 89, TRUE)
) AS items(id, item, category, price, in_stock)
""")
rel.bitstring_agg("id", min=1, max=6, groups="category", projected_columns="category").order("category")
Result
┌──────────┬─────────────────────────┐
│ category │ bitstring_agg(id, 1, 6) │
│ varchar │ bit │
├──────────┼─────────────────────────┤
│ clothing │ 111000 │
│ tools │ 000111 │
└──────────┴─────────────────────────┘
bool_and
bool_and(self, expression: str, groups: str = '', window_spec: str = '', projected_columns: str = '') -> DuckDBPyRelation
Computes the logical AND of all values present in a given expression.
Parameters
-
expression : str
The column or expression to perform the boolean AND aggregation on.
-
groups : str, default: ''
Comma-separated list of columns to include in the
GROUP BY; cannot be combined withwindow_spec. -
window_spec : str, default: ''
Window specification, written as
OVER (PARTITION BY ... ORDER BY ...); cannot be combined withgroups. -
projected_columns : str, default: ''
Comma-separated list of columns to include in the result.
Example
import duckdb
duckdb_conn = duckdb.connect()
rel = duckdb_conn.sql("""
SELECT *
FROM (VALUES
(1, 'jeans', 'clothing', 20, TRUE),
(2, 't-shirt', 'clothing', 8, FALSE),
(3, 'jacket', 'clothing', 65, TRUE),
(4, 'hammer', 'tools', 42, TRUE),
(5, 'screwdriver', 'tools', 7, TRUE),
(6, 'drill', 'tools', 89, TRUE)
) AS items(id, item, category, price, in_stock)
""")
rel.bool_and("in_stock", groups="category", projected_columns="category").order("category")
Result
┌──────────┬────────────────────┐
│ category │ bool_and(in_stock) │
│ varchar │ boolean │
├──────────┼────────────────────┤
│ clothing │ false │
│ tools │ true │
└──────────┴────────────────────┘
bool_or
bool_or(self, expression: str, groups: str = '', window_spec: str = '', projected_columns: str = '') -> DuckDBPyRelation
Computes the logical OR of all values present in a given expression.
Parameters
-
expression : str
The column or expression to perform the boolean OR aggregation on.
-
groups : str, default: ''
Comma-separated list of columns to include in the
GROUP BY; cannot be combined withwindow_spec. -
window_spec : str, default: ''
Window specification, written as
OVER (PARTITION BY ... ORDER BY ...); cannot be combined withgroups. -
projected_columns : str, default: ''
Comma-separated list of columns to include in the result.
Example
import duckdb
duckdb_conn = duckdb.connect()
rel = duckdb_conn.sql("""
SELECT *
FROM (VALUES
(1, 'jeans', 'clothing', 20, TRUE),
(2, 't-shirt', 'clothing', 8, FALSE),
(3, 'jacket', 'clothing', 65, TRUE),
(4, 'hammer', 'tools', 42, TRUE),
(5, 'screwdriver', 'tools', 7, TRUE),
(6, 'drill', 'tools', 89, TRUE)
) AS items(id, item, category, price, in_stock)
""")
rel.bool_or("in_stock", groups="category", projected_columns="category").order("category")
Result
┌──────────┬───────────────────┐
│ category │ bool_or(in_stock) │
│ varchar │ boolean │
├──────────┼───────────────────┤
│ clothing │ true │
│ tools │ true │
└──────────┴───────────────────┘
count
count(self, expression: str, groups: str = '', window_spec: str = '', projected_columns: str = '') -> DuckDBPyRelation
Computes the number of elements present in a given expression.
Parameters
-
expression : str
The column or expression to count the values of;
'*'counts the rows. -
groups : str, default: ''
Comma-separated list of columns to include in the
GROUP BY; cannot be combined withwindow_spec. -
window_spec : str, default: ''
Window specification, written as
OVER (PARTITION BY ... ORDER BY ...); cannot be combined withgroups. -
projected_columns : str, default: ''
Comma-separated list of columns to include in the result.
Example
import duckdb
duckdb_conn = duckdb.connect()
rel = duckdb_conn.sql("""
SELECT *
FROM (VALUES
(1, 'jeans', 'clothing', 20, TRUE),
(2, 't-shirt', 'clothing', 8, FALSE),
(3, 'jacket', 'clothing', 65, TRUE),
(4, 'hammer', 'tools', 42, TRUE),
(5, 'screwdriver', 'tools', 7, TRUE),
(6, 'drill', 'tools', 89, TRUE)
) AS items(id, item, category, price, in_stock)
""")
rel.count("id")
Result
┌───────────┐
│ count(id) │
│ int64 │
├───────────┤
│ 6 │
└───────────┘
cume_dist
cume_dist(self, window_spec: str, projected_columns: str = '') -> DuckDBPyRelation
Computes the cumulative distribution within the partition.
Parameters
-
window_spec : str
Window specification, written as
OVER (PARTITION BY ... ORDER BY ...). -
projected_columns : str, default: ''
Comma-separated list of columns to include in the result.
Example
import duckdb
duckdb_conn = duckdb.connect()
rel = duckdb_conn.sql("""
SELECT *
FROM (VALUES
(1, 'jeans', 'clothing', 20, TRUE),
(2, 't-shirt', 'clothing', 8, FALSE),
(3, 'jacket', 'clothing', 65, TRUE),
(4, 'hammer', 'tools', 42, TRUE),
(5, 'screwdriver', 'tools', 7, TRUE),
(6, 'drill', 'tools', 89, TRUE)
) AS items(id, item, category, price, in_stock)
""")
rel.cume_dist(window_spec="OVER (PARTITION BY category ORDER BY price)", projected_columns="category, item, price").order("category, price")
Result
┌──────────┬─────────────┬───────┬─────────────────────────────────────────────────────────┐
│ category │ item │ price │ cume_dist() OVER (PARTITION BY category ORDER BY price) │
│ varchar │ varchar │ int32 │ double │
├──────────┼─────────────┼───────┼─────────────────────────────────────────────────────────┤
│ clothing │ t-shirt │ 8 │ 0.3333333333333333 │
│ clothing │ jeans │ 20 │ 0.6666666666666666 │
│ clothing │ jacket │ 65 │ 1.0 │
│ tools │ screwdriver │ 7 │ 0.3333333333333333 │
│ tools │ hammer │ 42 │ 0.6666666666666666 │
│ tools │ drill │ 89 │ 1.0 │
└──────────┴─────────────┴───────┴─────────────────────────────────────────────────────────┘
dense_rank
dense_rank(self, window_spec: str, projected_columns: str = '') -> DuckDBPyRelation
Computes the dense rank within the partition.
Aliases: rank_dense
Parameters
-
window_spec : str
Window specification, written as
OVER (PARTITION BY ... ORDER BY ...). -
projected_columns : str, default: ''
Comma-separated list of columns to include in the result.
Example
import duckdb
duckdb_conn = duckdb.connect()
rel = duckdb_conn.sql("""
SELECT *
FROM (VALUES
(1, 'jeans', 'clothing', 20, TRUE),
(2, 't-shirt', 'clothing', 8, FALSE),
(3, 'jacket', 'clothing', 65, TRUE),
(4, 'hammer', 'tools', 42, TRUE),
(5, 'screwdriver', 'tools', 7, TRUE),
(6, 'drill', 'tools', 89, TRUE)
) AS items(id, item, category, price, in_stock)
""")
rel.dense_rank(window_spec="OVER (PARTITION BY category ORDER BY price)", projected_columns="category, item, price").order("category, price")
Result
┌──────────┬─────────────┬───────┬──────────────────────────────────────────────────────────┐
│ category │ item │ price │ dense_rank() OVER (PARTITION BY category ORDER BY price) │
│ varchar │ varchar │ int32 │ int64 │
├──────────┼─────────────┼───────┼──────────────────────────────────────────────────────────┤
│ clothing │ t-shirt │ 8 │ 1 │
│ clothing │ jeans │ 20 │ 2 │
│ clothing │ jacket │ 65 │ 3 │
│ tools │ screwdriver │ 7 │ 1 │
│ tools │ hammer │ 42 │ 2 │
│ tools │ drill │ 89 │ 3 │
└──────────┴─────────────┴───────┴──────────────────────────────────────────────────────────┘
favg
favg(self, expression: str, groups: str = '', window_spec: str = '', projected_columns: str = '') -> DuckDBPyRelation
Computes the average of all values present in a given expression using a more accurate floating point summation (Kahan Sum).
Parameters
-
expression : str
The column or expression to calculate the average of.
-
groups : str, default: ''
Comma-separated list of columns to include in the
GROUP BY; cannot be combined withwindow_spec. -
window_spec : str, default: ''
Window specification, written as
OVER (PARTITION BY ... ORDER BY ...); cannot be combined withgroups. -
projected_columns : str, default: ''
Comma-separated list of columns to include in the result.
Example
import duckdb
duckdb_conn = duckdb.connect()
rel = duckdb_conn.sql("""
SELECT *
FROM (VALUES
(1, 'jeans', 'clothing', 20, TRUE),
(2, 't-shirt', 'clothing', 8, FALSE),
(3, 'jacket', 'clothing', 65, TRUE),
(4, 'hammer', 'tools', 42, TRUE),
(5, 'screwdriver', 'tools', 7, TRUE),
(6, 'drill', 'tools', 89, TRUE)
) AS items(id, item, category, price, in_stock)
""")
rel.favg("price", groups="category", projected_columns="category").order("category")
Result
┌──────────┬─────────────┐
│ category │ favg(price) │
│ varchar │ double │
├──────────┼─────────────┤
│ clothing │ 31.0 │
│ tools │ 46.0 │
└──────────┴─────────────┘
first
first(self, expression: str, groups: str = '', projected_columns: str = '') -> DuckDBPyRelation
Returns the first value of a given expression.
Parameters
-
expression : str
The column or expression from which to retrieve the first value.
-
groups : str, default: ''
Comma-separated list of columns to include in the
GROUP BY. -
projected_columns : str, default: ''
Comma-separated list of columns to include in the result.
Example
import duckdb
duckdb_conn = duckdb.connect()
rel = duckdb_conn.sql("""
SELECT *
FROM (VALUES
(1, 'jeans', 'clothing', 20, TRUE),
(2, 't-shirt', 'clothing', 8, FALSE),
(3, 'jacket', 'clothing', 65, TRUE),
(4, 'hammer', 'tools', 42, TRUE),
(5, 'screwdriver', 'tools', 7, TRUE),
(6, 'drill', 'tools', 89, TRUE)
) AS items(id, item, category, price, in_stock)
""")
rel.first("item", groups="category", projected_columns="category").order("category")
Result
┌──────────┬───────────────┐
│ category │ "first"(item) │
│ varchar │ varchar │
├──────────┼───────────────┤
│ clothing │ jeans │
│ tools │ hammer │
└──────────┴───────────────┘
first_value
first_value(self, expression: str, window_spec: str = '', projected_columns: str = '') -> DuckDBPyRelation
Computes the first value within the group or partition.
Parameters
-
expression : str
The column or expression from which to retrieve the first value within the window.
-
window_spec : str, default: ''
Window specification, written as
OVER (PARTITION BY ... ORDER BY ...). -
projected_columns : str, default: ''
Comma-separated list of columns to include in the result.
Example
import duckdb
duckdb_conn = duckdb.connect()
rel = duckdb_conn.sql("""
SELECT *
FROM (VALUES
(1, 'jeans', 'clothing', 20, TRUE),
(2, 't-shirt', 'clothing', 8, FALSE),
(3, 'jacket', 'clothing', 65, TRUE),
(4, 'hammer', 'tools', 42, TRUE),
(5, 'screwdriver', 'tools', 7, TRUE),
(6, 'drill', 'tools', 89, TRUE)
) AS items(id, item, category, price, in_stock)
""")
rel.first_value("item", window_spec="OVER (PARTITION BY category ORDER BY price)", projected_columns="category").distinct().order("category")
Result
┌──────────┬───────────────────────────────────────────────────────────────┐
│ category │ first_value(item) OVER (PARTITION BY category ORDER BY price) │
│ varchar │ varchar │
├──────────┼───────────────────────────────────────────────────────────────┤
│ clothing │ t-shirt │
│ tools │ screwdriver │
└──────────┴───────────────────────────────────────────────────────────────┘
fsum
fsum(self, expression: str, groups: str = '', window_spec: str = '', projected_columns: str = '') -> DuckDBPyRelation
Computes the sum of all values present in a given expression using a more accurate floating point summation (Kahan Sum).
Parameters
-
expression : str
The column or expression to calculate the sum of.
-
groups : str, default: ''
Comma-separated list of columns to include in the
GROUP BY; cannot be combined withwindow_spec. -
window_spec : str, default: ''
Window specification, written as
OVER (PARTITION BY ... ORDER BY ...); cannot be combined withgroups. -
projected_columns : str, default: ''
Comma-separated list of columns to include in the result.
Example
import duckdb
duckdb_conn = duckdb.connect()
rel = duckdb_conn.sql("""
SELECT *
FROM (VALUES
(1, 'jeans', 'clothing', 20, TRUE),
(2, 't-shirt', 'clothing', 8, FALSE),
(3, 'jacket', 'clothing', 65, TRUE),
(4, 'hammer', 'tools', 42, TRUE),
(5, 'screwdriver', 'tools', 7, TRUE),
(6, 'drill', 'tools', 89, TRUE)
) AS items(id, item, category, price, in_stock)
""")
rel.fsum("price", groups="category", projected_columns="category").order("category")
Result
┌──────────┬─────────────┐
│ category │ fsum(price) │
│ varchar │ double │
├──────────┼─────────────┤
│ clothing │ 93.0 │
│ tools │ 138.0 │
└──────────┴─────────────┘
geomean
geomean(self, expression: str, groups: str = '', projected_columns: str = '') -> DuckDBPyRelation
Computes the geometric mean over all values present in a given expression.
Parameters
-
expression : str
The column or expression to calculate the geometric mean of.
-
groups : str, default: ''
Comma-separated list of columns to include in the
GROUP BY. -
projected_columns : str, default: ''
Comma-separated list of columns to include in the result.
Example
import duckdb
duckdb_conn = duckdb.connect()
rel = duckdb_conn.sql("""
SELECT *
FROM (VALUES
(1, 'jeans', 'clothing', 20, TRUE),
(2, 't-shirt', 'clothing', 8, FALSE),
(3, 'jacket', 'clothing', 65, TRUE),
(4, 'hammer', 'tools', 42, TRUE),
(5, 'screwdriver', 'tools', 7, TRUE),
(6, 'drill', 'tools', 89, TRUE)
) AS items(id, item, category, price, in_stock)
""")
rel.geomean("price", groups="category", projected_columns="category").order("category")
Result
┌──────────┬────────────────────┐
│ category │ geomean(price) │
│ varchar │ double │
├──────────┼────────────────────┤
│ clothing │ 21.827857661222115 │
│ tools │ 29.68787497217981 │
└──────────┴────────────────────┘
histogram
histogram(self, expression: str, groups: str = '', window_spec: str = '', projected_columns: str = '') -> DuckDBPyRelation
Computes the histogram over all values present in a given expression.
Parameters
-
expression : str
The column or expression to calculate the histogram of.
-
groups : str, default: ''
Comma-separated list of columns to include in the
GROUP BY; cannot be combined withwindow_spec. -
window_spec : str, default: ''
Window specification, written as
OVER (PARTITION BY ... ORDER BY ...); cannot be combined withgroups. -
projected_columns : str, default: ''
Comma-separated list of columns to include in the result.
Example
import duckdb
duckdb_conn = duckdb.connect()
rel = duckdb_conn.sql("""
SELECT *
FROM (VALUES
(1, 'jeans', 'clothing', 20, TRUE),
(2, 't-shirt', 'clothing', 8, FALSE),
(3, 'jacket', 'clothing', 65, TRUE),
(4, 'hammer', 'tools', 42, TRUE),
(5, 'screwdriver', 'tools', 7, TRUE),
(6, 'drill', 'tools', 89, TRUE)
) AS items(id, item, category, price, in_stock)
""")
rel.histogram("in_stock", groups="category", projected_columns="category").order("category")
Result
┌──────────┬───────────────────────┐
│ category │ histogram(in_stock) │
│ varchar │ map(boolean, ubigint) │
├──────────┼───────────────────────┤
│ clothing │ {false=1, true=2} │
│ tools │ {true=3} │
└──────────┴───────────────────────┘
lag
lag(self, expression: str, window_spec: str, offset: int = 1, default_value: str = 'NULL', ignore_nulls: bool = False, projected_columns: str = '') -> DuckDBPyRelation
Computes the lag within the partition.
Parameters
-
expression : str
The column or expression to apply the lag function on.
-
window_spec : str
Window specification, written as
OVER (PARTITION BY ... ORDER BY ...). -
offset : int, default: 1
The number of rows to lag behind.
-
default_value : str, default: 'NULL'
The value, as SQL text, to return when the lag offset goes out of bounds.
-
ignore_nulls : bool, default: False
Whether to ignore NULL values when computing the lag.
-
projected_columns : str, default: ''
Comma-separated list of columns to include in the result.
Example
import duckdb
duckdb_conn = duckdb.connect()
rel = duckdb_conn.sql("""
SELECT *
FROM (VALUES
(1, 'jeans', 'clothing', 20, TRUE),
(2, 't-shirt', 'clothing', 8, FALSE),
(3, 'jacket', 'clothing', 65, TRUE),
(4, 'hammer', 'tools', 42, TRUE),
(5, 'screwdriver', 'tools', 7, TRUE),
(6, 'drill', 'tools', 89, TRUE)
) AS items(id, item, category, price, in_stock)
""")
rel.lag("item", window_spec="OVER (ORDER BY price)", projected_columns="item, price").order("price")
Result
┌─────────────┬───────┬──────────────────────────────────────────┐
│ item │ price │ lag(item, 1, NULL) OVER (ORDER BY price) │
│ varchar │ int32 │ varchar │
├─────────────┼───────┼──────────────────────────────────────────┤
│ screwdriver │ 7 │ NULL │
│ t-shirt │ 8 │ screwdriver │
│ jeans │ 20 │ t-shirt │
│ hammer │ 42 │ jeans │
│ jacket │ 65 │ hammer │
│ drill │ 89 │ jacket │
└─────────────┴───────┴──────────────────────────────────────────┘
last
last(self, expression: str, groups: str = '', projected_columns: str = '') -> DuckDBPyRelation
Returns the last value of a given expression.
Parameters
-
expression : str
The column or expression from which to retrieve the last value.
-
groups : str, default: ''
Comma-separated list of columns to include in the
GROUP BY. -
projected_columns : str, default: ''
Comma-separated list of columns to include in the result.
Example
import duckdb
duckdb_conn = duckdb.connect()
rel = duckdb_conn.sql("""
SELECT *
FROM (VALUES
(1, 'jeans', 'clothing', 20, TRUE),
(2, 't-shirt', 'clothing', 8, FALSE),
(3, 'jacket', 'clothing', 65, TRUE),
(4, 'hammer', 'tools', 42, TRUE),
(5, 'screwdriver', 'tools', 7, TRUE),
(6, 'drill', 'tools', 89, TRUE)
) AS items(id, item, category, price, in_stock)
""")
rel.last("item", groups="category", projected_columns="category").order("category")
Result
┌──────────┬──────────────┐
│ category │ "last"(item) │
│ varchar │ varchar │
├──────────┼──────────────┤
│ clothing │ jacket │
│ tools │ drill │
└──────────┴──────────────┘
last_value
last_value(self, expression: str, window_spec: str = '', projected_columns: str = '') -> DuckDBPyRelation
Computes the last value within the group or partition.
Parameters
-
expression : str
The column or expression from which to retrieve the last value within the window.
-
window_spec : str, default: ''
Window specification, written as
OVER (PARTITION BY ... ORDER BY ...). -
projected_columns : str, default: ''
Comma-separated list of columns to include in the result.
Example
import duckdb
duckdb_conn = duckdb.connect()
rel = duckdb_conn.sql("""
SELECT *
FROM (VALUES
(1, 'jeans', 'clothing', 20, TRUE),
(2, 't-shirt', 'clothing', 8, FALSE),
(3, 'jacket', 'clothing', 65, TRUE),
(4, 'hammer', 'tools', 42, TRUE),
(5, 'screwdriver', 'tools', 7, TRUE),
(6, 'drill', 'tools', 89, TRUE)
) AS items(id, item, category, price, in_stock)
""")
rel.last_value("item", window_spec="OVER (PARTITION BY category ORDER BY price ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)", projected_columns="category").distinct().order("category")
Result
┌──────────┬───────────────────────────────────────────────────────────────────────────────────────────────────────────┐
│ category │ last_value(item) OVER (PARTITION BY category ORDER BY price ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDE │
│ │ D FOLLOWING) │
│ varchar │ varchar │
├──────────┼───────────────────────────────────────────────────────────────────────────────────────────────────────────┤
│ clothing │ jacket │
├──────────┼───────────────────────────────────────────────────────────────────────────────────────────────────────────┤
│ tools │ drill │
└──────────┴───────────────────────────────────────────────────────────────────────────────────────────────────────────┘
lead
lead(self, expression: str, window_spec: str, offset: int = 1, default_value: str = 'NULL', ignore_nulls: bool = False, projected_columns: str = '') -> DuckDBPyRelation
Computes the lead within the partition.
Parameters
-
expression : str
The column or expression to apply the lead function on.
-
window_spec : str
Window specification, written as
OVER (PARTITION BY ... ORDER BY ...). -
offset : int, default: 1
The number of rows to lead ahead.
-
default_value : str, default: 'NULL'
The value, as SQL text, to return when the lead offset goes out of bounds.
-
ignore_nulls : bool, default: False
Whether to ignore NULL values when computing the lead.
-
projected_columns : str, default: ''
Comma-separated list of columns to include in the result.
Example
import duckdb
duckdb_conn = duckdb.connect()
rel = duckdb_conn.sql("""
SELECT *
FROM (VALUES
(1, 'jeans', 'clothing', 20, TRUE),
(2, 't-shirt', 'clothing', 8, FALSE),
(3, 'jacket', 'clothing', 65, TRUE),
(4, 'hammer', 'tools', 42, TRUE),
(5, 'screwdriver', 'tools', 7, TRUE),
(6, 'drill', 'tools', 89, TRUE)
) AS items(id, item, category, price, in_stock)
""")
rel.lead("item", window_spec="OVER (ORDER BY price)", projected_columns="item, price").order("price")
Result
┌─────────────┬───────┬───────────────────────────────────────────┐
│ item │ price │ lead(item, 1, NULL) OVER (ORDER BY price) │
│ varchar │ int32 │ varchar │
├─────────────┼───────┼───────────────────────────────────────────┤
│ screwdriver │ 7 │ t-shirt │
│ t-shirt │ 8 │ jeans │
│ jeans │ 20 │ hammer │
│ hammer │ 42 │ jacket │
│ jacket │ 65 │ drill │
│ drill │ 89 │ NULL │
└─────────────┴───────┴───────────────────────────────────────────┘
list
list(self, expression: str, groups: str = '', window_spec: str = '', projected_columns: str = '') -> DuckDBPyRelation
Returns a list containing all values present in a given expression.
Parameters
-
expression : str
The column or expression to aggregate values into a list.
-
groups : str, default: ''
Comma-separated list of columns to include in the
GROUP BY; cannot be combined withwindow_spec. -
window_spec : str, default: ''
Window specification, written as
OVER (PARTITION BY ... ORDER BY ...); cannot be combined withgroups. -
projected_columns : str, default: ''
Comma-separated list of columns to include in the result.
Example
import duckdb
duckdb_conn = duckdb.connect()
rel = duckdb_conn.sql("""
SELECT *
FROM (VALUES
(1, 'jeans', 'clothing', 20, TRUE),
(2, 't-shirt', 'clothing', 8, FALSE),
(3, 'jacket', 'clothing', 65, TRUE),
(4, 'hammer', 'tools', 42, TRUE),
(5, 'screwdriver', 'tools', 7, TRUE),
(6, 'drill', 'tools', 89, TRUE)
) AS items(id, item, category, price, in_stock)
""")
rel.list("item", groups="category", projected_columns="category").order("category")
Result
┌──────────┬──────────────────────────────┐
│ category │ list(item) │
│ varchar │ varchar[] │
├──────────┼──────────────────────────────┤
│ clothing │ [jeans, t-shirt, jacket] │
│ tools │ [hammer, screwdriver, drill] │
└──────────┴──────────────────────────────┘
max
max(self, expression: str, groups: str = '', window_spec: str = '', projected_columns: str = '') -> DuckDBPyRelation
Returns the maximum value present in a given expression.
Parameters
-
expression : str
The column or expression to calculate the maximum value of.
-
groups : str, default: ''
Comma-separated list of columns to include in the
GROUP BY; cannot be combined withwindow_spec. -
window_spec : str, default: ''
Window specification, written as
OVER (PARTITION BY ... ORDER BY ...); cannot be combined withgroups. -
projected_columns : str, default: ''
Comma-separated list of columns to include in the result.
Example
import duckdb
duckdb_conn = duckdb.connect()
rel = duckdb_conn.sql("""
SELECT *
FROM (VALUES
(1, 'jeans', 'clothing', 20, TRUE),
(2, 't-shirt', 'clothing', 8, FALSE),
(3, 'jacket', 'clothing', 65, TRUE),
(4, 'hammer', 'tools', 42, TRUE),
(5, 'screwdriver', 'tools', 7, TRUE),
(6, 'drill', 'tools', 89, TRUE)
) AS items(id, item, category, price, in_stock)
""")
rel.max("price", groups="category", projected_columns="category").order("category")
Result
┌──────────┬────────────┐
│ category │ max(price) │
│ varchar │ int32 │
├──────────┼────────────┤
│ clothing │ 65 │
│ tools │ 89 │
└──────────┴────────────┘
mean
mean(self, expression: str, groups: str = '', window_spec: str = '', projected_columns: str = '') -> DuckDBPyRelation
Alias of avg().
median
median(self, expression: str, groups: str = '', window_spec: str = '', projected_columns: str = '') -> DuckDBPyRelation
Computes the median over all values present in a given expression.
Parameters
-
expression : str
The column or expression to calculate the median value of.
-
groups : str, default: ''
Comma-separated list of columns to include in the
GROUP BY; cannot be combined withwindow_spec. -
window_spec : str, default: ''
Window specification, written as
OVER (PARTITION BY ... ORDER BY ...); cannot be combined withgroups. -
projected_columns : str, default: ''
Comma-separated list of columns to include in the result.
Example
import duckdb
duckdb_conn = duckdb.connect()
rel = duckdb_conn.sql("""
SELECT *
FROM (VALUES
(1, 'jeans', 'clothing', 20, TRUE),
(2, 't-shirt', 'clothing', 8, FALSE),
(3, 'jacket', 'clothing', 65, TRUE),
(4, 'hammer', 'tools', 42, TRUE),
(5, 'screwdriver', 'tools', 7, TRUE),
(6, 'drill', 'tools', 89, TRUE)
) AS items(id, item, category, price, in_stock)
""")
rel.median("price", groups="category", projected_columns="category").order("category")
Result
┌──────────┬───────────────┐
│ category │ median(price) │
│ varchar │ double │
├──────────┼───────────────┤
│ clothing │ 20.0 │
│ tools │ 42.0 │
└──────────┴───────────────┘
min
min(self, expression: str, groups: str = '', window_spec: str = '', projected_columns: str = '') -> DuckDBPyRelation
Returns the minimum value present in a given expression.
Parameters
-
expression : str
The column or expression to calculate the min value of.
-
groups : str, default: ''
Comma-separated list of columns to include in the
GROUP BY; cannot be combined withwindow_spec. -
window_spec : str, default: ''
Window specification, written as
OVER (PARTITION BY ... ORDER BY ...); cannot be combined withgroups. -
projected_columns : str, default: ''
Comma-separated list of columns to include in the result.
Example
import duckdb
duckdb_conn = duckdb.connect()
rel = duckdb_conn.sql("""
SELECT *
FROM (VALUES
(1, 'jeans', 'clothing', 20, TRUE),
(2, 't-shirt', 'clothing', 8, FALSE),
(3, 'jacket', 'clothing', 65, TRUE),
(4, 'hammer', 'tools', 42, TRUE),
(5, 'screwdriver', 'tools', 7, TRUE),
(6, 'drill', 'tools', 89, TRUE)
) AS items(id, item, category, price, in_stock)
""")
rel.min("price", groups="category", projected_columns="category").order("category")
Result
┌──────────┬────────────┐
│ category │ min(price) │
│ varchar │ int32 │
├──────────┼────────────┤
│ clothing │ 8 │
│ tools │ 7 │
└──────────┴────────────┘
mode
mode(self, expression: str, groups: str = '', window_spec: str = '', projected_columns: str = '') -> DuckDBPyRelation
Computes the mode over all values present in a given expression.
Parameters
-
expression : str
The column or expression to calculate the mode (most frequent value) of.
-
groups : str, default: ''
Comma-separated list of columns to include in the
GROUP BY; cannot be combined withwindow_spec. -
window_spec : str, default: ''
Window specification, written as
OVER (PARTITION BY ... ORDER BY ...); cannot be combined withgroups. -
projected_columns : str, default: ''
Comma-separated list of columns to include in the result.
Example
import duckdb
duckdb_conn = duckdb.connect()
sales = duckdb_conn.sql("""
SELECT *
FROM (VALUES ('clothing', 20), ('clothing', 20), ('clothing', 8), ('tools', 42), ('tools', 7), ('tools', 7))
AS sales(category, price)
""")
sales.mode("price", groups="category", projected_columns="category").order("category")
Result
┌──────────┬───────────────┐
│ category │ "mode"(price) │
│ varchar │ int32 │
├──────────┼───────────────┤
│ clothing │ 20 │
│ tools │ 7 │
└──────────┴───────────────┘
n_tile
n_tile(self, window_spec: str, num_buckets: int, projected_columns: str = '') -> DuckDBPyRelation
Divides the partition as equally as possible into num_buckets.
Parameters
-
window_spec : str
Window specification, written as
OVER (PARTITION BY ... ORDER BY ...). -
num_buckets : int
The number of buckets to divide the rows into.
-
projected_columns : str, default: ''
Comma-separated list of columns to include in the result.
Example
import duckdb
duckdb_conn = duckdb.connect()
rel = duckdb_conn.sql("""
SELECT *
FROM (VALUES
(1, 'jeans', 'clothing', 20, TRUE),
(2, 't-shirt', 'clothing', 8, FALSE),
(3, 'jacket', 'clothing', 65, TRUE),
(4, 'hammer', 'tools', 42, TRUE),
(5, 'screwdriver', 'tools', 7, TRUE),
(6, 'drill', 'tools', 89, TRUE)
) AS items(id, item, category, price, in_stock)
""")
rel.n_tile(window_spec="OVER (PARTITION BY category ORDER BY price)", num_buckets=2, projected_columns="category, item, price").order("category, price")
Result
┌──────────┬─────────────┬───────┬──────────────────────────────────────────────────────┐
│ category │ item │ price │ ntile(2) OVER (PARTITION BY category ORDER BY price) │
│ varchar │ varchar │ int32 │ int64 │
├──────────┼─────────────┼───────┼──────────────────────────────────────────────────────┤
│ clothing │ t-shirt │ 8 │ 1 │
│ clothing │ jeans │ 20 │ 1 │
│ clothing │ jacket │ 65 │ 2 │
│ tools │ screwdriver │ 7 │ 1 │
│ tools │ hammer │ 42 │ 1 │
│ tools │ drill │ 89 │ 2 │
└──────────┴─────────────┴───────┴──────────────────────────────────────────────────────┘
nth_value
nth_value(self, expression: str, window_spec: str, offset: int, ignore_nulls: bool = False, projected_columns: str = '') -> DuckDBPyRelation
Computes the nth value within the partition.
Parameters
-
expression : str
The column or expression from which to retrieve the nth value within the window.
-
window_spec : str
Window specification, written as
OVER (PARTITION BY ... ORDER BY ...). -
offset : int
The position of the value to retrieve within the window (1-based index).
-
ignore_nulls : bool, default: False
Whether to ignore NULL values when computing the nth value.
-
projected_columns : str, default: ''
Comma-separated list of columns to include in the result.
Example
import duckdb
duckdb_conn = duckdb.connect()
rel = duckdb_conn.sql("""
SELECT *
FROM (VALUES
(1, 'jeans', 'clothing', 20, TRUE),
(2, 't-shirt', 'clothing', 8, FALSE),
(3, 'jacket', 'clothing', 65, TRUE),
(4, 'hammer', 'tools', 42, TRUE),
(5, 'screwdriver', 'tools', 7, TRUE),
(6, 'drill', 'tools', 89, TRUE)
) AS items(id, item, category, price, in_stock)
""")
rel.nth_value("item", window_spec="OVER (PARTITION BY category ORDER BY price)", offset=2, projected_columns="category, item, price").order("category, price")
Result
┌──────────┬─────────────┬───────┬────────────────────────────────────────────────────────────────┐
│ category │ item │ price │ nth_value(item, 2) OVER (PARTITION BY category ORDER BY price) │
│ varchar │ varchar │ int32 │ varchar │
├──────────┼─────────────┼───────┼────────────────────────────────────────────────────────────────┤
│ clothing │ t-shirt │ 8 │ NULL │
│ clothing │ jeans │ 20 │ jeans │
│ clothing │ jacket │ 65 │ jeans │
│ tools │ screwdriver │ 7 │ NULL │
│ tools │ hammer │ 42 │ hammer │
│ tools │ drill │ 89 │ hammer │
└──────────┴─────────────┴───────┴────────────────────────────────────────────────────────────────┘
percent_rank
percent_rank(self, window_spec: str, projected_columns: str = '') -> DuckDBPyRelation
Computes the relative rank within the partition.
Parameters
-
window_spec : str
Window specification, written as
OVER (PARTITION BY ... ORDER BY ...). -
projected_columns : str, default: ''
Comma-separated list of columns to include in the result.
Example
import duckdb
duckdb_conn = duckdb.connect()
rel = duckdb_conn.sql("""
SELECT *
FROM (VALUES
(1, 'jeans', 'clothing', 20, TRUE),
(2, 't-shirt', 'clothing', 8, FALSE),
(3, 'jacket', 'clothing', 65, TRUE),
(4, 'hammer', 'tools', 42, TRUE),
(5, 'screwdriver', 'tools', 7, TRUE),
(6, 'drill', 'tools', 89, TRUE)
) AS items(id, item, category, price, in_stock)
""")
rel.percent_rank(window_spec="OVER (PARTITION BY category ORDER BY price)", projected_columns="category, item, price").order("category, price")
Result
┌──────────┬─────────────┬───────┬────────────────────────────────────────────────────────────┐
│ category │ item │ price │ percent_rank() OVER (PARTITION BY category ORDER BY price) │
│ varchar │ varchar │ int32 │ double │
├──────────┼─────────────┼───────┼────────────────────────────────────────────────────────────┤
│ clothing │ t-shirt │ 8 │ 0.0 │
│ clothing │ jeans │ 20 │ 0.5 │
│ clothing │ jacket │ 65 │ 1.0 │
│ tools │ screwdriver │ 7 │ 0.0 │
│ tools │ hammer │ 42 │ 0.5 │
│ tools │ drill │ 89 │ 1.0 │
└──────────┴─────────────┴───────┴────────────────────────────────────────────────────────────┘
product
product(self, expression: str, groups: str = '', window_spec: str = '', projected_columns: str = '') -> DuckDBPyRelation
Returns the product of all values present in a given expression.
Parameters
-
expression : str
The column or expression to calculate the product of.
-
groups : str, default: ''
Comma-separated list of columns to include in the
GROUP BY; cannot be combined withwindow_spec. -
window_spec : str, default: ''
Window specification, written as
OVER (PARTITION BY ... ORDER BY ...); cannot be combined withgroups. -
projected_columns : str, default: ''
Comma-separated list of columns to include in the result.
Example
import duckdb
duckdb_conn = duckdb.connect()
rel = duckdb_conn.sql("""
SELECT *
FROM (VALUES
(1, 'jeans', 'clothing', 20, TRUE),
(2, 't-shirt', 'clothing', 8, FALSE),
(3, 'jacket', 'clothing', 65, TRUE),
(4, 'hammer', 'tools', 42, TRUE),
(5, 'screwdriver', 'tools', 7, TRUE),
(6, 'drill', 'tools', 89, TRUE)
) AS items(id, item, category, price, in_stock)
""")
rel.product("price", groups="category", projected_columns="category").order("category")
Result
┌──────────┬────────────────┐
│ category │ product(price) │
│ varchar │ double │
├──────────┼────────────────┤
│ clothing │ 10400.0 │
│ tools │ 26166.0 │
└──────────┴────────────────┘
quantile
quantile(self, expression: str, q: float | builtins.list[float] = 0.5, groups: str = '', window_spec: str = '', projected_columns: str = '') -> DuckDBPyRelation
Alias of quantile_disc().
quantile_cont
quantile_cont(self, expression: str, q: float | builtins.list[float] = 0.5, groups: str = '', window_spec: str = '', projected_columns: str = '') -> DuckDBPyRelation
Computes the interpolated quantile value for a given expression.
Parameters
-
expression : str
The column or expression to compute the continuous quantile for.
-
q : float, list[float], default: 0.5
The quantile to compute, such as 0.5 for the median, or a list of quantiles.
-
groups : str, default: ''
Comma-separated list of columns to include in the
GROUP BY; cannot be combined withwindow_spec. -
window_spec : str, default: ''
Window specification, written as
OVER (PARTITION BY ... ORDER BY ...); cannot be combined withgroups. -
projected_columns : str, default: ''
Comma-separated list of columns to include in the result.
Example
import duckdb
duckdb_conn = duckdb.connect()
rel = duckdb_conn.sql("""
SELECT *
FROM (VALUES
(1, 'jeans', 'clothing', 20, TRUE),
(2, 't-shirt', 'clothing', 8, FALSE),
(3, 'jacket', 'clothing', 65, TRUE),
(4, 'hammer', 'tools', 42, TRUE),
(5, 'screwdriver', 'tools', 7, TRUE),
(6, 'drill', 'tools', 89, TRUE)
) AS items(id, item, category, price, in_stock)
""")
rel.quantile_cont("price", groups="category", projected_columns="category").order("category")
Result
┌──────────┬────────────────────────────────┐
│ category │ quantile_cont(price, 0.500000) │
│ varchar │ double │
├──────────┼────────────────────────────────┤
│ clothing │ 20.0 │
│ tools │ 42.0 │
└──────────┴────────────────────────────────┘
quantile_disc
quantile_disc(self, expression: str, q: float | builtins.list[float] = 0.5, groups: str = '', window_spec: str = '', projected_columns: str = '') -> DuckDBPyRelation
Computes the exact quantile value for a given expression.
Aliases: quantile
Parameters
-
expression : str
The column or expression to compute the discrete quantile for.
-
q : float, list[float], default: 0.5
The quantile to compute, such as 0.5 for the median, or a list of quantiles.
-
groups : str, default: ''
Comma-separated list of columns to include in the
GROUP BY; cannot be combined withwindow_spec. -
window_spec : str, default: ''
Window specification, written as
OVER (PARTITION BY ... ORDER BY ...); cannot be combined withgroups. -
projected_columns : str, default: ''
Comma-separated list of columns to include in the result.
Example
import duckdb
duckdb_conn = duckdb.connect()
rel = duckdb_conn.sql("""
SELECT *
FROM (VALUES
(1, 'jeans', 'clothing', 20, TRUE),
(2, 't-shirt', 'clothing', 8, FALSE),
(3, 'jacket', 'clothing', 65, TRUE),
(4, 'hammer', 'tools', 42, TRUE),
(5, 'screwdriver', 'tools', 7, TRUE),
(6, 'drill', 'tools', 89, TRUE)
) AS items(id, item, category, price, in_stock)
""")
rel.quantile_disc("price", groups="category", projected_columns="category").order("category")
Result
┌──────────┬────────────────────────────────┐
│ category │ quantile_disc(price, 0.500000) │
│ varchar │ int32 │
├──────────┼────────────────────────────────┤
│ clothing │ 20 │
│ tools │ 42 │
└──────────┴────────────────────────────────┘
rank
rank(self, window_spec: str, projected_columns: str = '') -> DuckDBPyRelation
Computes the rank within the partition.
Parameters
-
window_spec : str
Window specification, written as
OVER (PARTITION BY ... ORDER BY ...). -
projected_columns : str, default: ''
Comma-separated list of columns to include in the result.
Example
import duckdb
duckdb_conn = duckdb.connect()
rel = duckdb_conn.sql("""
SELECT *
FROM (VALUES
(1, 'jeans', 'clothing', 20, TRUE),
(2, 't-shirt', 'clothing', 8, FALSE),
(3, 'jacket', 'clothing', 65, TRUE),
(4, 'hammer', 'tools', 42, TRUE),
(5, 'screwdriver', 'tools', 7, TRUE),
(6, 'drill', 'tools', 89, TRUE)
) AS items(id, item, category, price, in_stock)
""")
rel.rank(window_spec="OVER (PARTITION BY category ORDER BY price)", projected_columns="category, item, price").order("category, price")
Result
┌──────────┬─────────────┬───────┬────────────────────────────────────────────────────┐
│ category │ item │ price │ rank() OVER (PARTITION BY category ORDER BY price) │
│ varchar │ varchar │ int32 │ int64 │
├──────────┼─────────────┼───────┼────────────────────────────────────────────────────┤
│ clothing │ t-shirt │ 8 │ 1 │
│ clothing │ jeans │ 20 │ 2 │
│ clothing │ jacket │ 65 │ 3 │
│ tools │ screwdriver │ 7 │ 1 │
│ tools │ hammer │ 42 │ 2 │
│ tools │ drill │ 89 │ 3 │
└──────────┴─────────────┴───────┴────────────────────────────────────────────────────┘
rank_dense
rank_dense(self, window_spec: str, projected_columns: str = '') -> DuckDBPyRelation
Alias of dense_rank().
row_number
row_number(self, window_spec: str, projected_columns: str = '') -> DuckDBPyRelation
Computes the row number within the partition.
Parameters
-
window_spec : str
Window specification, written as
OVER (PARTITION BY ... ORDER BY ...). -
projected_columns : str, default: ''
Comma-separated list of columns to include in the result.
Example
import duckdb
duckdb_conn = duckdb.connect()
rel = duckdb_conn.sql("""
SELECT *
FROM (VALUES
(1, 'jeans', 'clothing', 20, TRUE),
(2, 't-shirt', 'clothing', 8, FALSE),
(3, 'jacket', 'clothing', 65, TRUE),
(4, 'hammer', 'tools', 42, TRUE),
(5, 'screwdriver', 'tools', 7, TRUE),
(6, 'drill', 'tools', 89, TRUE)
) AS items(id, item, category, price, in_stock)
""")
rel.row_number(window_spec="OVER (PARTITION BY category ORDER BY price)", projected_columns="category, item, price").order("category, price")
Result
┌──────────┬─────────────┬───────┬──────────────────────────────────────────────────────────┐
│ category │ item │ price │ row_number() OVER (PARTITION BY category ORDER BY price) │
│ varchar │ varchar │ int32 │ int64 │
├──────────┼─────────────┼───────┼──────────────────────────────────────────────────────────┤
│ clothing │ t-shirt │ 8 │ 1 │
│ clothing │ jeans │ 20 │ 2 │
│ clothing │ jacket │ 65 │ 3 │
│ tools │ screwdriver │ 7 │ 1 │
│ tools │ hammer │ 42 │ 2 │
│ tools │ drill │ 89 │ 3 │
└──────────┴─────────────┴───────┴──────────────────────────────────────────────────────────┘
std
std(self, expression: str, groups: str = '', window_spec: str = '', projected_columns: str = '') -> DuckDBPyRelation
Alias of stddev_samp().
stddev
stddev(self, expression: str, groups: str = '', window_spec: str = '', projected_columns: str = '') -> DuckDBPyRelation
Alias of stddev_samp().
stddev_pop
stddev_pop(self, expression: str, groups: str = '', window_spec: str = '', projected_columns: str = '') -> DuckDBPyRelation
Computes the population standard deviation for a given expression.
Parameters
-
expression : str
The column or expression to calculate the standard deviation for.
-
groups : str, default: ''
Comma-separated list of columns to include in the
GROUP BY; cannot be combined withwindow_spec. -
window_spec : str, default: ''
Window specification, written as
OVER (PARTITION BY ... ORDER BY ...); cannot be combined withgroups. -
projected_columns : str, default: ''
Comma-separated list of columns to include in the result.
Example
import duckdb
duckdb_conn = duckdb.connect()
rel = duckdb_conn.sql("""
SELECT *
FROM (VALUES
(1, 'jeans', 'clothing', 20, TRUE),
(2, 't-shirt', 'clothing', 8, FALSE),
(3, 'jacket', 'clothing', 65, TRUE),
(4, 'hammer', 'tools', 42, TRUE),
(5, 'screwdriver', 'tools', 7, TRUE),
(6, 'drill', 'tools', 89, TRUE)
) AS items(id, item, category, price, in_stock)
""")
rel.stddev_pop("price", groups="category", projected_columns="category").order("category")
Result
┌──────────┬────────────────────┐
│ category │ stddev_pop(price) │
│ varchar │ double │
├──────────┼────────────────────┤
│ clothing │ 24.535688292770594 │
│ tools │ 33.595634637057636 │
└──────────┴────────────────────┘
stddev_samp
stddev_samp(self, expression: str, groups: str = '', window_spec: str = '', projected_columns: str = '') -> DuckDBPyRelation
Computes the sample standard deviation for a given expression.
Parameters
-
expression : str
The column or expression to calculate the standard deviation for.
-
groups : str, default: ''
Comma-separated list of columns to include in the
GROUP BY; cannot be combined withwindow_spec. -
window_spec : str, default: ''
Window specification, written as
OVER (PARTITION BY ... ORDER BY ...); cannot be combined withgroups. -
projected_columns : str, default: ''
Comma-separated list of columns to include in the result.
Example
import duckdb
duckdb_conn = duckdb.connect()
rel = duckdb_conn.sql("""
SELECT *
FROM (VALUES
(1, 'jeans', 'clothing', 20, TRUE),
(2, 't-shirt', 'clothing', 8, FALSE),
(3, 'jacket', 'clothing', 65, TRUE),
(4, 'hammer', 'tools', 42, TRUE),
(5, 'screwdriver', 'tools', 7, TRUE),
(6, 'drill', 'tools', 89, TRUE)
) AS items(id, item, category, price, in_stock)
""")
rel.stddev_samp("price", groups="category", projected_columns="category").order("category")
Result
┌──────────┬────────────────────┐
│ category │ stddev_samp(price) │
│ varchar │ double │
├──────────┼────────────────────┤
│ clothing │ 30.04995840263344 │
│ tools │ 41.14608122288197 │
└──────────┴────────────────────┘
string_agg
string_agg(self, expression: str, sep: str = ',', groups: str = '', window_spec: str = '', projected_columns: str = '') -> DuckDBPyRelation
Concatenates the values present in a given expression with a separator.
Parameters
-
expression : str
The column or expression to concatenate values from.
-
sep : str, default: ','
Separator string to use between concatenated values.
-
groups : str, default: ''
Comma-separated list of columns to include in the
GROUP BY; cannot be combined withwindow_spec. -
window_spec : str, default: ''
Window specification, written as
OVER (PARTITION BY ... ORDER BY ...); cannot be combined withgroups. -
projected_columns : str, default: ''
Comma-separated list of columns to include in the result.
Example
import duckdb
duckdb_conn = duckdb.connect()
rel = duckdb_conn.sql("""
SELECT *
FROM (VALUES
(1, 'jeans', 'clothing', 20, TRUE),
(2, 't-shirt', 'clothing', 8, FALSE),
(3, 'jacket', 'clothing', 65, TRUE),
(4, 'hammer', 'tools', 42, TRUE),
(5, 'screwdriver', 'tools', 7, TRUE),
(6, 'drill', 'tools', 89, TRUE)
) AS items(id, item, category, price, in_stock)
""")
rel.string_agg("item", sep=", ", groups="category", projected_columns="category").order("category")
Result
┌──────────┬────────────────────────────┐
│ category │ string_agg(item, ', ') │
│ varchar │ varchar │
├──────────┼────────────────────────────┤
│ clothing │ jeans, t-shirt, jacket │
│ tools │ hammer, screwdriver, drill │
└──────────┴────────────────────────────┘
sum
sum(self, expression: str, groups: str = '', window_spec: str = '', projected_columns: str = '') -> DuckDBPyRelation
Computes the sum of all values present in a given expression.
Parameters
-
expression : str
The column or expression to calculate the sum for.
-
groups : str, default: ''
Comma-separated list of columns to include in the
GROUP BY; cannot be combined withwindow_spec. -
window_spec : str, default: ''
Window specification, written as
OVER (PARTITION BY ... ORDER BY ...); cannot be combined withgroups. -
projected_columns : str, default: ''
Comma-separated list of columns to include in the result.
Example
import duckdb
duckdb_conn = duckdb.connect()
rel = duckdb_conn.sql("""
SELECT *
FROM (VALUES
(1, 'jeans', 'clothing', 20, TRUE),
(2, 't-shirt', 'clothing', 8, FALSE),
(3, 'jacket', 'clothing', 65, TRUE),
(4, 'hammer', 'tools', 42, TRUE),
(5, 'screwdriver', 'tools', 7, TRUE),
(6, 'drill', 'tools', 89, TRUE)
) AS items(id, item, category, price, in_stock)
""")
rel.sum("price", groups="category", projected_columns="category").order("category")
Result
┌──────────┬────────────┐
│ category │ sum(price) │
│ varchar │ int128 │
├──────────┼────────────┤
│ clothing │ 93 │
│ tools │ 138 │
└──────────┴────────────┘
unique
unique(self, unique_aggr: str) -> DuckDBPyRelation
Returns the distinct values in a column.
Parameters
-
unique_aggr : str
The column to get the distinct values for.
Example
import duckdb
duckdb_conn = duckdb.connect()
rel = duckdb_conn.sql("""
SELECT *
FROM (VALUES
(1, 'jeans', 'clothing', 20, TRUE),
(2, 't-shirt', 'clothing', 8, FALSE),
(3, 'jacket', 'clothing', 65, TRUE),
(4, 'hammer', 'tools', 42, TRUE),
(5, 'screwdriver', 'tools', 7, TRUE),
(6, 'drill', 'tools', 89, TRUE)
) AS items(id, item, category, price, in_stock)
""")
rel.unique("category").order("category")
Result
┌──────────┐
│ category │
│ varchar │
├──────────┤
│ clothing │
│ tools │
└──────────┘
value_counts
value_counts(self, expression: str, groups: str = '') -> DuckDBPyRelation
Computes the number of elements present in a given expression, also projecting the original expression.
Parameters
-
expression : str
The column or expression to count values from.
-
groups : str, default: ''
Comma-separated list of columns to include in the
GROUP BY.
Example
import duckdb
duckdb_conn = duckdb.connect()
rel = duckdb_conn.sql("""
SELECT *
FROM (VALUES
(1, 'jeans', 'clothing', 20, TRUE),
(2, 't-shirt', 'clothing', 8, FALSE),
(3, 'jacket', 'clothing', 65, TRUE),
(4, 'hammer', 'tools', 42, TRUE),
(5, 'screwdriver', 'tools', 7, TRUE),
(6, 'drill', 'tools', 89, TRUE)
) AS items(id, item, category, price, in_stock)
""")
rel.value_counts("in_stock", groups="in_stock").order("in_stock")
Result
┌──────────┬─────────────────┐
│ in_stock │ count(in_stock) │
│ boolean │ int64 │
├──────────┼─────────────────┤
│ false │ 1 │
│ true │ 5 │
└──────────┴─────────────────┘
var
var(self, expression: str, groups: str = '', window_spec: str = '', projected_columns: str = '') -> DuckDBPyRelation
Alias of var_samp().
var_pop
var_pop(self, expression: str, groups: str = '', window_spec: str = '', projected_columns: str = '') -> DuckDBPyRelation
Computes the population variance for a given expression.
Parameters
-
expression : str
The column or expression to calculate the population variance for.
-
groups : str, default: ''
Comma-separated list of columns to include in the
GROUP BY; cannot be combined withwindow_spec. -
window_spec : str, default: ''
Window specification, written as
OVER (PARTITION BY ... ORDER BY ...); cannot be combined withgroups. -
projected_columns : str, default: ''
Comma-separated list of columns to include in the result.
Example
import duckdb
duckdb_conn = duckdb.connect()
rel = duckdb_conn.sql("""
SELECT *
FROM (VALUES
(1, 'jeans', 'clothing', 20, TRUE),
(2, 't-shirt', 'clothing', 8, FALSE),
(3, 'jacket', 'clothing', 65, TRUE),
(4, 'hammer', 'tools', 42, TRUE),
(5, 'screwdriver', 'tools', 7, TRUE),
(6, 'drill', 'tools', 89, TRUE)
) AS items(id, item, category, price, in_stock)
""")
rel.var_pop("price", groups="category", projected_columns="category").order("category")
Result
┌──────────┬────────────────────┐
│ category │ var_pop(price) │
│ varchar │ double │
├──────────┼────────────────────┤
│ clothing │ 602.0 │
│ tools │ 1128.6666666666667 │
└──────────┴────────────────────┘
var_samp
var_samp(self, expression: str, groups: str = '', window_spec: str = '', projected_columns: str = '') -> DuckDBPyRelation
Computes the sample variance for a given expression.
Parameters
-
expression : str
The column or expression to calculate the sample variance for.
-
groups : str, default: ''
Comma-separated list of columns to include in the
GROUP BY; cannot be combined withwindow_spec. -
window_spec : str, default: ''
Window specification, written as
OVER (PARTITION BY ... ORDER BY ...); cannot be combined withgroups. -
projected_columns : str, default: ''
Comma-separated list of columns to include in the result.
Example
import duckdb
duckdb_conn = duckdb.connect()
rel = duckdb_conn.sql("""
SELECT *
FROM (VALUES
(1, 'jeans', 'clothing', 20, TRUE),
(2, 't-shirt', 'clothing', 8, FALSE),
(3, 'jacket', 'clothing', 65, TRUE),
(4, 'hammer', 'tools', 42, TRUE),
(5, 'screwdriver', 'tools', 7, TRUE),
(6, 'drill', 'tools', 89, TRUE)
) AS items(id, item, category, price, in_stock)
""")
rel.var_samp("price", groups="category", projected_columns="category").order("category")
Result
┌──────────┬─────────────────┐
│ category │ var_samp(price) │
│ varchar │ double │
├──────────┼─────────────────┤
│ clothing │ 903.0 │
│ tools │ 1693.0 │
└──────────┴─────────────────┘
variance
variance(self, expression: str, groups: str = '', window_spec: str = '', projected_columns: str = '') -> DuckDBPyRelation
Alias of var_samp().
Output
This section contains the methods which read the relation, store it in a table, a view or a file, or write to the table it reads.
| Name | Description |
|---|---|
insert |
Inserts the given values into the relation. |
insert_into |
Inserts the relation object into an existing table named table_name. |
update |
Update the given relation with the provided expressions. |
arrow |
Alias of to_arrow_reader(). |
close |
Does nothing: a relation holds no result. |
create |
Creates a new table named table_name with the contents of the relation object. |
create_view |
Creates a view named view_name that refers to the relation object. |
df |
Execute and fetch all rows as a pandas DataFrame. |
fetch_arrow_reader |
Deprecated alias of to_arrow_reader(). |
fetch_arrow_table |
Deprecated alias of to_arrow_table(). |
fetch_record_batch |
Deprecated alias of to_arrow_reader(). |
fetchall |
Execute and fetch all rows as a list of tuples. |
fetchdf |
Alias of df(). |
fetchnumpy |
Execute and fetch all rows as a Python dict mapping each column to one numpy arrays. |
iter_rows |
Every row, a batch at a time, over one run of the relation. |
materialize |
Execute once and return a relation over the rows, held in client memory. |
pl |
Execute and fetch all rows as a Polars DataFrame. |
tf |
Fetch a result as dict of TensorFlow Tensors. |
to_arrow_reader |
Execute and return an Arrow Record Batch Reader that yields all rows. |
to_arrow_table |
Execute and fetch all rows as an Arrow Table. |
to_csv |
Alias of write_csv(). |
to_df |
Alias of df(). |
to_dicts |
Every row, as a dict keyed by column name. |
to_parquet |
Alias of write_parquet(). |
to_table |
Alias of create(). |
to_view |
Alias of create_view(). |
torch |
Fetch a result as dict of PyTorch Tensors. |
write_csv |
Write the relation object to a CSV file in 'file_name'. |
write_parquet |
Write the relation object to a Parquet file in 'file_name'. |
insert
insert(self, values: object) -> None
Inserts the given values into the relation.
The relation must read a table, as one from table() does. The relation runs again on every read, so reading it afterwards shows the new rows.
Parameters
-
values : tuple, list, object
The values of one row in the order of the table's columns: a tuple, a list or, for a table of one column, a single value.
Example
import duckdb
duckdb_conn = duckdb.connect()
duckdb_conn.sql("CREATE TABLE items (item VARCHAR, price INTEGER)")
rel = duckdb_conn.table("items")
rel.insert(("jeans", 20))
rel.insert(["hammer", 42])
rel.order("item")
Result
┌─────────┬───────┐
│ item │ price │
│ varchar │ int32 │
├─────────┼───────┤
│ hammer │ 42 │
│ jeans │ 20 │
└─────────┴───────┘
insert_into
insert_into(self, table_name: str) -> None
Inserts the relation object into an existing table named table_name.
The name is table, schema.table or catalog.schema.table, and a part may be double quoted; a name of more than three parts needs SQL (INSERT INTO) for now.
Parameters
-
table_name : str
The name of the table:
table,schema.tableorcatalog.schema.table; a name of more parts raisesNotImplementedException. The table must exist, and the relation must have its columns in the table's column order.
Example
import duckdb
duckdb_conn = duckdb.connect()
duckdb_conn.sql("CREATE TABLE items (item VARCHAR, price INTEGER)")
rel = duckdb_conn.values(("jeans", 20), ("hammer", 42))
rel.insert_into("items")
duckdb_conn.table("items").order("item")
Result
┌─────────┬───────┐
│ item │ price │
│ varchar │ int32 │
├─────────┼───────┤
│ hammer │ 42 │
│ jeans │ 20 │
└─────────┴───────┘
update
update(self, set: object, *, condition: object = None) -> None
Update the given relation with the provided expressions.
The relation must read a table, as one from table() does. The relation runs again on every read, so reading it afterwards shows the updated rows.
Parameters
-
set : dict
The new values, as a dict of column name to an Expression or a Python value. A string value raises
TypeError: writecol('y')for the columny, orlit('y')for the text. -
condition : str, Expression, keyword-only, default: None
Optional condition to filter which rows to update.
Example
import duckdb
from duckdb import col, lit
duckdb_conn = duckdb.connect()
duckdb_conn.sql("CREATE TABLE items AS SELECT * FROM (VALUES (1, 'jeans', 20), (2, 'hammer', 42)) AS t(id, item, price)")
rel = duckdb_conn.table("items")
rel.update(set={"item": lit("claw hammer"), "price": col("price") + 5}, condition=col("id") == 2)
rel.order("id")
Result
┌───────┬─────────────┬───────┐
│ id │ item │ price │
│ int32 │ varchar │ int32 │
├───────┼─────────────┼───────┤
│ 1 │ jeans │ 20 │
│ 2 │ claw hammer │ 47 │
└───────┴─────────────┴───────┘
arrow
arrow(self, batch_size: int = 131072) -> Any
Alias of to_arrow_reader().
We recommend using
to_arrow_reader()instead.
close
close(self) -> None
Does nothing: a relation holds no result.
create
create(self, table_name: str) -> None
Creates a new table named table_name with the contents of the relation object.
The name is table, schema.table or catalog.schema.table, and a part may be double quoted; a name of more than three parts needs SQL (CREATE TABLE AS) for now.
Aliases: to_table
Parameters
-
table_name : str
The name of the table:
table,schema.tableorcatalog.schema.table; a name of more parts raisesNotImplementedException. There must not be a table of that name already.
Example
import duckdb
duckdb_conn = duckdb.connect()
rel = duckdb_conn.sql("""
SELECT *
FROM (VALUES
(1, 'jeans', 'clothing', 20, TRUE),
(2, 't-shirt', 'clothing', 8, FALSE),
(3, 'jacket', 'clothing', 65, TRUE),
(4, 'hammer', 'tools', 42, TRUE),
(5, 'screwdriver', 'tools', 7, TRUE),
(6, 'drill', 'tools', 89, TRUE)
) AS items(id, item, category, price, in_stock)
""")
rel.filter("category = 'tools'").create("tools")
duckdb_conn.table("tools")
Result
┌───────┬─────────────┬──────────┬───────┬──────────┐
│ id │ item │ category │ price │ in_stock │
│ int32 │ varchar │ varchar │ int32 │ boolean │
├───────┼─────────────┼──────────┼───────┼──────────┤
│ 4 │ hammer │ tools │ 42 │ true │
│ 5 │ screwdriver │ tools │ 7 │ true │
│ 6 │ drill │ tools │ 89 │ true │
└───────┴─────────────┴──────────┴───────┴──────────┘
create_view
create_view(self, view_name: str, replace: bool = True) -> DuckDBPyRelation
Creates a view named view_name that refers to the relation object.
A view stores SQL text, so a relation over rows that DuckDB holds for it cannot become one: a relation from values() or materialize() or over a statement that ran at the call, such as an INSERT, raises InvalidInputException. Use create() to store such rows in a table, or con.register(name, rel) for a temporary view that lasts as long as the connection.
Aliases: to_view
Parameters
-
view_name : str
The name of the view to be created.
-
replace : bool, default: True
If the view should be created with
CREATE OR REPLACE. When set toFalse, there must not be a view of that name already.
Example
import duckdb
duckdb_conn = duckdb.connect()
rel = duckdb_conn.sql("""
SELECT *
FROM (VALUES
(1, 'jeans', 'clothing', 20, TRUE),
(2, 't-shirt', 'clothing', 8, FALSE),
(3, 'jacket', 'clothing', 65, TRUE),
(4, 'hammer', 'tools', 42, TRUE),
(5, 'screwdriver', 'tools', 7, TRUE),
(6, 'drill', 'tools', 89, TRUE)
) AS items(id, item, category, price, in_stock)
""")
rel.filter("price > 30").create_view("expensive_items")
duckdb_conn.view("expensive_items")
Result
┌───────┬─────────┬──────────┬───────┬──────────┐
│ id │ item │ category │ price │ in_stock │
│ int32 │ varchar │ varchar │ int32 │ boolean │
├───────┼─────────┼──────────┼───────┼──────────┤
│ 3 │ jacket │ clothing │ 65 │ true │
│ 4 │ hammer │ tools │ 42 │ true │
│ 6 │ drill │ tools │ 89 │ true │
└───────┴─────────┴──────────┴───────┴──────────┘
df
df(self, *, date_as_object: bool = False) -> Any
Execute and fetch all rows as a pandas DataFrame.
Parameters
-
date_as_object : bool, keyword-only, default: False
If the date columns should be interpreted as Python date objects.
Example
import duckdb
duckdb_conn = duckdb.connect()
rel = duckdb_conn.sql("""
SELECT *
FROM (VALUES
(1, 'jeans', 'clothing', 20, TRUE),
(2, 't-shirt', 'clothing', 8, FALSE),
(3, 'jacket', 'clothing', 65, TRUE),
(4, 'hammer', 'tools', 42, TRUE),
(5, 'screwdriver', 'tools', 7, TRUE),
(6, 'drill', 'tools', 89, TRUE)
) AS items(id, item, category, price, in_stock)
""")
rel.df()
Result
id item category price in_stock
0 1 jeans clothing 20 True
1 2 t-shirt clothing 8 False
2 3 jacket clothing 65 True
3 4 hammer tools 42 True
4 5 screwdriver tools 7 True
5 6 drill tools 89 True
fetch_arrow_reader
fetch_arrow_reader(self, batch_size: int = 131072) -> Any
Deprecated alias of to_arrow_reader().
Deprecated
fetch_arrow_reader()is deprecated. Useto_arrow_reader()instead.
fetch_arrow_table
fetch_arrow_table(self, batch_size: int = 131072) -> Any
Deprecated alias of to_arrow_table().
Deprecated
fetch_arrow_table()is deprecated. Useto_arrow_table()instead.
fetch_record_batch
fetch_record_batch(self, rows_per_batch: int = 131072) -> Any
Deprecated alias of to_arrow_reader().
Deprecated
fetch_record_batch()is deprecated. Useto_arrow_reader()instead.
fetchall
fetchall(self) -> builtins.list[tuple[Any, ...]]
Execute and fetch all rows as a list of tuples.
Example
import duckdb
duckdb_conn = duckdb.connect()
rel = duckdb_conn.sql("""
SELECT *
FROM (VALUES
(1, 'jeans', 'clothing', 20, TRUE),
(2, 't-shirt', 'clothing', 8, FALSE),
(3, 'jacket', 'clothing', 65, TRUE),
(4, 'hammer', 'tools', 42, TRUE),
(5, 'screwdriver', 'tools', 7, TRUE),
(6, 'drill', 'tools', 89, TRUE)
) AS items(id, item, category, price, in_stock)
""")
rel.limit(1).fetchall()
Result
[(1, 'jeans', 'clothing', 20, True)]
fetchdf
fetchdf(self, *, date_as_object: bool = False) -> Any
Alias of df().
fetchnumpy
fetchnumpy(self) -> dict[str, Any]
Execute and fetch all rows as a Python dict mapping each column to one numpy arrays.
Example
import duckdb
duckdb_conn = duckdb.connect()
rel = duckdb_conn.sql("""
SELECT *
FROM (VALUES
(1, 'jeans', 'clothing', 20, TRUE),
(2, 't-shirt', 'clothing', 8, FALSE),
(3, 'jacket', 'clothing', 65, TRUE),
(4, 'hammer', 'tools', 42, TRUE),
(5, 'screwdriver', 'tools', 7, TRUE),
(6, 'drill', 'tools', 89, TRUE)
) AS items(id, item, category, price, in_stock)
""")
rel.fetchnumpy()
Result
{'id': array([1, 2, 3, 4, 5, 6], dtype=int32), 'item': array(['jeans', 't-shirt', 'jacket', 'hammer', 'screwdriver', 'drill'],
dtype=object), 'category': array(['clothing', 'clothing', 'clothing', 'tools', 'tools', 'tools'],
dtype=object), 'price': array([20, 8, 65, 42, 7, 89], dtype=int32), 'in_stock': array([ True, False, True, True, True, True])}
iter_rows
iter_rows(self, batch_size: int = 1024) -> Iterator[tuple[Any, ...]]
Every row, a batch at a time, over one run of the relation.
The rows are read once into the engine's memory, so every batch comes from the same run and the connection is free between batches; the caller holds one batch at a time rather than the whole result.
To read a relation row by row, as a loop over fetchone() or fetchmany() did before DuckDB 2.0, iterate over iter_rows().
Parameters
-
batch_size : int, default: 1024
The number of rows fetched at a time; it must be above zero.
Example
import duckdb
duckdb_conn = duckdb.connect()
rel = duckdb_conn.sql("""
SELECT *
FROM (VALUES
(1, 'jeans', 'clothing', 20, TRUE),
(2, 't-shirt', 'clothing', 8, FALSE),
(3, 'jacket', 'clothing', 65, TRUE),
(4, 'hammer', 'tools', 42, TRUE),
(5, 'screwdriver', 'tools', 7, TRUE),
(6, 'drill', 'tools', 89, TRUE)
) AS items(id, item, category, price, in_stock)
""")
for row in rel.iter_rows(batch_size=4):
print(row)
Result
(1, 'jeans', 'clothing', 20, True)
(2, 't-shirt', 'clothing', 8, False)
(3, 'jacket', 'clothing', 65, True)
(4, 'hammer', 'tools', 42, True)
(5, 'screwdriver', 'tools', 7, True)
(6, 'drill', 'tools', 89, True)
materialize
materialize(self) -> DuckDBPyRelation
Execute once and return a relation over the rows, held in client memory.
The returned relation reads the held rows, so it does not see later changes to the data, and create_view() refuses it. materialize() takes the place of execute(), which relations no longer have since DuckDB 2.0.
Example
import duckdb
duckdb_conn = duckdb.connect()
duckdb_conn.sql("CREATE TABLE items AS SELECT range AS id FROM range(3)")
rel = duckdb_conn.table("items")
held = rel.materialize()
duckdb_conn.sql("INSERT INTO items VALUES (3)")
print(len(rel), len(held))
Result
4 3
pl
pl(self, batch_size: int = 131072, *, lazy: bool = False) -> Any
Execute and fetch all rows as a Polars DataFrame.
Needs the polars package.
Parameters
-
batch_size : int, default: 131072
The number of rows of each Arrow record batch.
-
lazy : bool, keyword-only, default: False
Return a polars
LazyFrameinstead of aDataFrame.
Example
import duckdb
duckdb_conn = duckdb.connect()
rel = duckdb_conn.sql("""
SELECT *
FROM (VALUES
(1, 'jeans', 'clothing', 20, TRUE),
(2, 't-shirt', 'clothing', 8, FALSE),
(3, 'jacket', 'clothing', 65, TRUE),
(4, 'hammer', 'tools', 42, TRUE),
(5, 'screwdriver', 'tools', 7, TRUE),
(6, 'drill', 'tools', 89, TRUE)
) AS items(id, item, category, price, in_stock)
""")
rel.pl(batch_size=1)
Result
shape: (6, 5)
┌─────┬─────────────┬──────────┬───────┬──────────┐
│ id ┆ item ┆ category ┆ price ┆ in_stock │
│ --- ┆ --- ┆ --- ┆ --- ┆ --- │
│ i32 ┆ str ┆ str ┆ i32 ┆ bool │
╞═════╪═════════════╪══════════╪═══════╪══════════╡
│ 1 ┆ jeans ┆ clothing ┆ 20 ┆ true │
│ 2 ┆ t-shirt ┆ clothing ┆ 8 ┆ false │
│ 3 ┆ jacket ┆ clothing ┆ 65 ┆ true │
│ 4 ┆ hammer ┆ tools ┆ 42 ┆ true │
│ 5 ┆ screwdriver ┆ tools ┆ 7 ┆ true │
│ 6 ┆ drill ┆ tools ┆ 89 ┆ true │
└─────┴─────────────┴──────────┴───────┴──────────┘
tf
tf(self) -> dict[str, Any]
Fetch a result as dict of TensorFlow Tensors.
Needs the tensorflow package.
to_arrow_reader
to_arrow_reader(self, batch_size: int = 131072) -> Any
Execute and return an Arrow Record Batch Reader that yields all rows.
Until the reader is read to the end or closed, the connection refuses other queries with ResourceInUseException. A with block closes the reader when it ends, also when the loop stops early. The example sets a small batch_size only to show several batches. To read the rows a batch at a time, as fetch_df_chunk() did before DuckDB 2.0, read the batches of this reader.
Aliases: arrow, fetch_arrow_reader, fetch_record_batch
Parameters
-
batch_size : int, default: 131072
The number of rows of each Arrow record batch.
Example
import duckdb
duckdb_conn = duckdb.connect()
rel = duckdb_conn.sql("""
SELECT *
FROM (VALUES
(1, 'jeans', 'clothing', 20, TRUE),
(2, 't-shirt', 'clothing', 8, FALSE),
(3, 'jacket', 'clothing', 65, TRUE),
(4, 'hammer', 'tools', 42, TRUE),
(5, 'screwdriver', 'tools', 7, TRUE),
(6, 'drill', 'tools', 89, TRUE)
) AS items(id, item, category, price, in_stock)
""")
with rel.select("item, price").to_arrow_reader(batch_size=2) as reader:
for batch in reader:
print(batch.to_pydict())
Result
{'item': ['jeans', 't-shirt'], 'price': [20, 8]}
{'item': ['jacket', 'hammer'], 'price': [65, 42]}
{'item': ['screwdriver', 'drill'], 'price': [7, 89]}
to_arrow_table
to_arrow_table(self, batch_size: int = 131072) -> Any
Execute and fetch all rows as an Arrow Table.
Aliases: fetch_arrow_table
Parameters
-
batch_size : int, default: 131072
The number of rows of each Arrow record batch.
Example
import duckdb
duckdb_conn = duckdb.connect()
rel = duckdb_conn.sql("""
SELECT *
FROM (VALUES
(1, 'jeans', 'clothing', 20, TRUE),
(2, 't-shirt', 'clothing', 8, FALSE),
(3, 'jacket', 'clothing', 65, TRUE),
(4, 'hammer', 'tools', 42, TRUE),
(5, 'screwdriver', 'tools', 7, TRUE),
(6, 'drill', 'tools', 89, TRUE)
) AS items(id, item, category, price, in_stock)
""")
rel.to_arrow_table()
Result
pyarrow.Table
id: int32
item: string
category: string
price: int32
in_stock: bool
----
id: [[1,2,3,4,5,6]]
item: [["jeans","t-shirt","jacket","hammer","screwdriver","drill"]]
category: [["clothing","clothing","clothing","tools","tools","tools"]]
price: [[20,8,65,42,7,89]]
in_stock: [[true,false,true,true,true,true]]
to_csv
to_csv(self, file_name: str, *, sep: str | None = None, na_rep: str | None = None, header: bool | None = None, quotechar: str | None = None, escapechar: str | None = None, date_format: str | None = None, timestamp_format: str | None = None, quoting: str | int | None = None, encoding: str | None = None, compression: str | None = None, overwrite: bool | None = None, per_thread_output: bool | None = None, use_tmp_file: bool | None = None, partition_by: builtins.list[str] | None = None, write_partition_columns: bool | None = None) -> None
Alias of write_csv().
to_df
to_df(self, *, date_as_object: bool = False) -> Any
Alias of df().
to_dicts
to_dicts(self) -> builtins.list[dict[str, Any]]
Every row, as a dict keyed by column name.
Example
import duckdb
duckdb_conn = duckdb.connect()
rel = duckdb_conn.sql("""
SELECT *
FROM (VALUES
(1, 'jeans', 'clothing', 20, TRUE),
(2, 't-shirt', 'clothing', 8, FALSE),
(3, 'jacket', 'clothing', 65, TRUE),
(4, 'hammer', 'tools', 42, TRUE),
(5, 'screwdriver', 'tools', 7, TRUE),
(6, 'drill', 'tools', 89, TRUE)
) AS items(id, item, category, price, in_stock)
""")
rel.limit(2).to_dicts()
Result
[{'id': 1, 'item': 'jeans', 'category': 'clothing', 'price': 20, 'in_stock': True}, {'id': 2, 'item': 't-shirt', 'category': 'clothing', 'price': 8, 'in_stock': False}]
to_parquet
to_parquet(self, file_name: str, *, compression: str | None = None, field_ids: object = None, row_group_size_bytes: int | str | None = None, row_group_size: int | None = None, overwrite: bool | None = None, per_thread_output: bool | None = None, use_tmp_file: bool | None = None, partition_by: builtins.list[str] | None = None, write_partition_columns: bool | None = None, append: bool | None = None, filename_pattern: str | None = None, file_size_bytes: str | int | None = None) -> None
Alias of write_parquet().
to_table
to_table(self, table_name: str) -> None
Alias of create().
to_view
to_view(self, view_name: str, replace: bool = True) -> DuckDBPyRelation
Alias of create_view().
torch
torch(self) -> dict[str, Any]
Fetch a result as dict of PyTorch Tensors.
Needs the torch package.
write_csv
write_csv(self, file_name: str, *, sep: str | None = None, na_rep: str | None = None, header: bool | None = None, quotechar: str | None = None, escapechar: str | None = None, date_format: str | None = None, timestamp_format: str | None = None, quoting: str | int | None = None, encoding: str | None = None, compression: str | None = None, overwrite: bool | None = None, per_thread_output: bool | None = None, use_tmp_file: bool | None = None, partition_by: builtins.list[str] | None = None, write_partition_columns: bool | None = None) -> None
Write the relation object to a CSV file in 'file_name'.
Most options are the option of the same name of the COPY ... TO statement; sep is DELIMITER, na_rep is NULL, quotechar is QUOTE, escapechar is ESCAPE, quoting sets FORCE_QUOTE for every column and overwrite is OVERWRITE_OR_IGNORE.
Aliases: to_csv
Parameters
-
file_name : str
Path of the CSV file to write; a directory with
partition_byorper_thread_output. -
sep : str, keyword-only, default: None
Delimiter between the columns; a comma when omitted.
-
na_rep : str, keyword-only, default: None
Text written for
NULLvalues; empty when omitted. -
header : bool, keyword-only, default: None
Whether to write a first line with the column names; written when omitted.
-
quotechar : str, keyword-only, default: None
Character used to quote values;
"when omitted. -
escapechar : str, keyword-only, default: None
Character written before a quote character inside a quoted value;
"when omitted. -
date_format : str, keyword-only, default: None
Format used to write dates.
-
timestamp_format : str, keyword-only, default: None
Format used to write timestamps.
-
quoting : str, int, keyword-only, default: None
Quote every value: pass
csv.QUOTE_ALL,'ALL'or'FORCE'; any other value is refused. Values are quoted only where needed when omitted. -
encoding : str, keyword-only, default: None
Only UTF-8 is accepted, written
'utf-8'or'utf8'. -
compression : str, keyword-only, default: None
Compression of the file:
'none','gzip'or'zstd'. Chosen from the file extension when omitted. -
overwrite : bool, keyword-only, default: None
Whether an existing file may be replaced. Omitted or
True, an existing file is replaced;Falserefuses an existing file withIOException. Withpartition_by, onlyTruewrites into a directory that already holds files. -
per_thread_output : bool, keyword-only, default: None
Write one file per thread into the directory
file_name, rather than one file. -
use_tmp_file : bool, keyword-only, default: None
Write to a temporary file first, so a cancelled write does not leave a broken file in place of an existing one.
-
partition_by : list[str], keyword-only, default: None
Columns to partition the output by, written as Hive partitioned directories under
file_name. -
write_partition_columns : bool, keyword-only, default: None
Whether to also write the partition columns into the files; only has an effect with
partition_by.
Example
import duckdb
duckdb_conn = duckdb.connect()
rel = duckdb_conn.sql("""
SELECT *
FROM (VALUES
(1, 'jeans', 'clothing', 20, TRUE),
(2, 't-shirt', 'clothing', 8, FALSE),
(3, 'jacket', 'clothing', 65, TRUE),
(4, 'hammer', 'tools', 42, TRUE),
(5, 'screwdriver', 'tools', 7, TRUE),
(6, 'drill', 'tools', 89, TRUE)
) AS items(id, item, category, price, in_stock)
""")
rel.write_csv("items.csv")
write_parquet
write_parquet(self, file_name: str, *, compression: str | None = None, field_ids: object = None, row_group_size_bytes: int | str | None = None, row_group_size: int | None = None, overwrite: bool | None = None, per_thread_output: bool | None = None, use_tmp_file: bool | None = None, partition_by: builtins.list[str] | None = None, write_partition_columns: bool | None = None, append: bool | None = None, filename_pattern: str | None = None, file_size_bytes: str | int | None = None) -> None
Write the relation object to a Parquet file in 'file_name'.
Each option is the option of the same name of the COPY ... TO statement, except overwrite, which is OVERWRITE_OR_IGNORE.
Aliases: to_parquet
Parameters
-
file_name : str
Path of the Parquet file to write; a directory with
partition_by,per_thread_outputorfile_size_bytes. -
compression : str, keyword-only, default: None
Compression codec:
'uncompressed','snappy','gzip','zstd','brotli','lz4'or'lz4_raw';'snappy'when omitted. -
field_ids : dict, str, keyword-only, default: None
The Parquet
field_idof each column, as a dict of column name to id, or'auto'to assign them. -
row_group_size_bytes : int, str, keyword-only, default: None
Target size of each row group, as a number of bytes or a text such as
'2MB'. -
row_group_size : int, keyword-only, default: None
Target number of rows of each row group; 122880 when omitted.
-
overwrite : bool, keyword-only, default: None
Whether an existing file may be replaced. Omitted or
True, an existing file is replaced;Falserefuses an existing file withIOException. Withpartition_by,Truewrites into a directory that already holds files, asappend=Truedoes. -
per_thread_output : bool, keyword-only, default: None
Write one file per thread into the directory
file_name, rather than one file. -
use_tmp_file : bool, keyword-only, default: None
Write to a temporary file first, so a cancelled write does not leave a broken file in place of an existing one.
-
partition_by : list[str], keyword-only, default: None
Columns to partition the output by, written as Hive partitioned directories under
file_name. -
write_partition_columns : bool, keyword-only, default: None
Whether to also write the partition columns into the files; only has an effect with
partition_by. -
append : bool, keyword-only, default: None
When a generated file name already exists, choose another name instead of overwriting the file; only has an effect when several files are written. Combined with
overwrite, it raisesBinderException. -
filename_pattern : str, keyword-only, default: None
Pattern of the names of the files written, where
{i}is replaced by an index and{uuid}by a UUID; only has an effect when several files are written. -
file_size_bytes : int, str, keyword-only, default: None
Start a new file in the directory
file_namewhen a file grows past this size, given as a number of bytes or a text such as'1MB'.
Example
import duckdb
duckdb_conn = duckdb.connect()
rel = duckdb_conn.sql("""
SELECT *
FROM (VALUES
(1, 'jeans', 'clothing', 20, TRUE),
(2, 't-shirt', 'clothing', 8, FALSE),
(3, 'jacket', 'clothing', 65, TRUE),
(4, 'hammer', 'tools', 42, TRUE),
(5, 'screwdriver', 'tools', 7, TRUE),
(6, 'drill', 'tools', 89, TRUE)
) AS items(id, item, category, price, in_stock)
""")
rel.write_parquet("items.parquet")