Python - pandas + duckdb 實現 SQL分析

2026-06-28

平常在資料清理的時候,都會想到如果是利用 Python 我們會怎麼操作資料清理跟截取呢。於是產生了這一篇文章的想法,讓我們來使用 pandas + duckdb 來實現吧!

1.使用工具

  • Python — 建立資料

    • pandas
    • pd.DataFrame
    • print()
  • duckdb — SQL 翻譯官

    • duckdb.execute()
    • duckdb.query().to_df()
    • SQL: CREATE OR REPLACE VIEW
    • select
    • coalesce()
    • round
    • left join
    • group by
    • order by
    • where
  1. 程式碼
import duckdb
import pandas as pd
 
# ----------------------------------------------------
# 步驟 1:用 Pandas 模擬讀取原始資料
# ----------------------------------------------------
# 員工表(包含一位還沒分配部門的新人「小李」)
df_employees = pd.DataFrame(
    {
      "emp_id": [101, 102, 103, 104, 105],
      "name": ["阿明", "小華", "大強", "美美", "小李"],
      "dept_id": ["D01", "D02", "D01", "D03", None],  # 小李暫無部門
      "salary": [60000, 75000, 55000, 90000, 50000],
    }
)
 
# 部門表
df_departments = pd.DataFrame(
    {
      "dept_id": ["D01", "D02", "D03"], 
      "dept_name": ["研發部", "市場部", "財務部"]
    }
)
 
# ----------------------------------------------------
# 步驟 2:用 VIEW 把複雜語法打包成「虛擬資料集」
# ----------------------------------------------------
# 1. 使用 OR REPLACE 確保重複執行程式時,會自動覆蓋舊邏輯而不報錯
# 2. 使用 LEFT JOIN 確保左表(員工)一個都不漏
# 3. 使用 COALESCE 把沒對到部門的 NULL 欄位漂亮地補上 '未分配'
duckdb.execute(
    """
    CREATE OR REPLACE VIEW v_dept_summary AS
    SELECT
        COALESCE(d.dept_name, '未分配部門') AS 部門,
        COUNT(e.emp_id) AS 總人數,
        ROUND(AVG(e.salary), 0) AS 平均薪資
    FROM df_employees AS e
    LEFT JOIN df_departments AS d ON e.dept_id = d.dept_id
    GROUP BY d.dept_name, e.dept_id
    """
)
 
# ----------------------------------------------------
# 步驟 3:在 Python 裡直接呼叫與二次利用這個資料集
# ----------------------------------------------------
# 應用 A:撈出整張整理好的報表,並加上排序
df_all = duckdb.query("SELECT * FROM v_dept_summary ORDER BY 平均薪資 DESC").to_df()
 
# 應用 B:針對同一個資料集做二次篩選(只要平均薪資大於 60000 的部門)
df_filter = duckdb.query("SELECT * FROM v_dept_summary WHERE 平均薪資 > 60000").to_df()
 
print("--- 應用 A:呼叫整個資料集並排序(小李被歸在未分配部門) ---")
print(df_all)
 
print("\n--- 應用 B:呼叫資料集並做二次篩選 ---")
print(df_filter)
  1. 結果

利用 pandas 與 duckdb 是不是能夠快速的讓我們抓取想要的資料呢!

# ----------------------------------------------------
# 結果
# ----------------------------------------------------
--- 應用 A:呼叫整個資料集並排序(小李被歸在未分配部門) ---
      部門     總人數    平均薪資
0    財務部      1      90000.0
1    市場部      1      75000.0
2    研發部      2      57500.0
3    未分配部門   1      50000.0
 
--- 應用 B:呼叫資料集並做二次篩選 ---
    部門  總人數   平均薪資
0  市場部    1    75000.0
1  財務部    1    90000.0

參考資料:

  • Python
  • Gemini