DuckDBPyRelation 作為 Polars 與 DuckDB 之間的橋樑,讓開發者得以在 Polars DataFrame 的操作中融入 SQL 的靈活性與 DuckDB 的高效能。這對於習慣使用 SQL 進行資料處理的工程師來說,無疑是一大利器。它不僅簡化了複雜資料操作的流程,更提升了整體的執行效率。DuckDBPyRelation 支援多種資料操作方式,包含直接使用 SQL 查詢、新增資料列、合併表格、篩選資料、聚合計算以及限制回傳資料列數等。透過 DuckDBPyRelation,開發者可以更輕鬆地處理 Polars DataFrame,並利用 SQL 的表達能力進行更精細的資料分析和處理,而無需在不同工具之間切換,有效提升開發效率。

DuckDBPyRelation:在 Polars DataFrame 中釋放 SQL 的力量

在資料分析的領域中,Polars 以其驚人的速度和效率,成為處理 DataFrame 的首選工具。但如果能將 SQL 的靈活性和 DuckDB 的效能融入 Polars 的工作流程中,會發生什麼事呢?這就是 DuckDBPyRelation 的用武之地。

探索 DuckDBPyRelation 的奧秘

DuckDBPyRelation 物件提供了一種獨特的方式,讓你能夠以 SQL 的方式查詢和操作 Polars DataFrame。你可以從 SQL 查詢或直接從 DuckDB 的連線物件建立 DuckDBPyRelation。

讓我們先建立一個 DuckDB 連線,並使用它來建立三個表格:customersproductssales

import duckdb
conn = duckdb.connect()

conn.execute('''
CREATE TABLE customers (customer_id INTEGER PRIMARY KEY, name STRING)
''')

conn.execute('''
CREATE TABLE products (product_id INTEGER PRIMARY KEY, product_name STRING)
''')

conn.execute('''
CREATE TABLE sales (customer_id INTEGER, product_id INTEGER, qty INTEGER,
PRIMARY KEY(customer_id, product_id))
''')

這段程式碼建立了三個簡單的表格,分別用於儲存客戶、產品和銷售資料。

現在,你可以使用 conn 物件的 table() 方法來載入特定的表格,例如:

customers_relation = conn.table('customers')

table() 方法的回傳值是一個 duckdb.DuckDBPyRelation 物件。你可以將這個物件轉換為 pandas 或 Polars DataFrame:

# 轉換為 pandas DataFrame
customers_relation.df()

# 轉換為 Polars DataFrame
customers_relation.pl()

使用 DuckDBPyRelation 進行資料操作

DuckDBPyRelation 不僅僅是一個查詢工具,它還能讓你直接操作資料。

新增資料列

你可以使用 insert() 函式將新的資料列插入表格中。以下程式碼示範如何將三筆資料插入 customers 表格:

customers_relation.insert([1, 'Alice'])
customers_relation.insert([2, 'Bob'])
customers_relation.insert([3, 'Charlie'])

同時,我們也將資料插入 productssales 表格:

products_relation = conn.table('products')
products_relation.insert([10, 'Paperclips'])
products_relation.insert([20, 'Staple'])
products_relation.insert([30, 'Notebook'])

sales_relation = conn.table("sales")
sales_relation.insert([1, 20, 1])
sales_relation.insert([1, 10, 2])
sales_relation.insert([2, 30, 7])
sales_relation.insert([3, 10, 3])
sales_relation.insert([3, 20, 2])

表格合併

有了代表三個表格的 DuckDBPyRelation 物件後,你可以使用 join() 方法來合併這些表格:

result = customers_relation.join(
    sales_relation,
    condition="customer_id",
    how="inner"
).join(
    products_relation,
    condition="product_id",
    how="inner"
)

這段程式碼將 customers 表格與 sales 表格合併,然後將結果與 products 表格合併。

資料篩選

在表格合併後,你可以使用 filter() 方法來提取你想要的資料列:

result.filter('customer_id = 1')

這段程式碼會篩選出 customer_id 為 1 的資料列,也就是 Alice 購買的產品。

或者,你也可以使用 execute() 方法並傳入 SQL 陳述式:

conn.execute('''
SELECT *
FROM result
WHERE customer_id = 1
''').pl()

資料聚合

DuckDBPyRelation 物件也支援資料聚合。假設你想計算所有客戶的購買總量,你可以使用 aggregate() 方法:

result.aggregate(
    'customer_id, MAX(name) AS Name, SUM(qty) as "Total Qty"',
    'customer_id'
)

這個聚合函式等同於以下的 GROUP BY 陳述式:

SELECT customer_id as 'Customer ID', MAX(name) AS Name, sum(qty) as 'Total Qty'
FROM result
GROUP BY customer_id

欄位選取

你可以使用 project() 方法來選取要顯示的特定欄位:

result.project('name, qty, product_name')

這段程式碼會顯示 nameqtyproduct_name 三個欄位。

資料列數限制

若要限制回傳的資料列數,可以使用 limit() 方法:

result.limit(3)

如果你想從第三列開始顯示接下來的三列,可以指定要顯示的列數和偏移量:

result.limit(3, 2)  # 顯示 3 列,從偏移量 2(第三列)開始

玄貓(BlackCat)觀點:DuckDBPyRelation 的價值

從玄貓(BlackCat)的經驗來看,DuckDBPyRelation 真正的價值在於它彌合了 Polars DataFrame 和 SQL 查詢之間的鴻溝。它不僅讓你能夠使用熟悉的 SQL 語法來查詢 DataFrame,還能利用 DuckDB 的效能優勢,加速資料處理的過程。

我認為,對於那些已經熟悉 SQL,並且希望在 Polars 的環境中利用 SQL 靈活性的資料科學家和工程師來說,DuckDBPyRelation 是一個非常棒的工具。