当前位置: 首页 > news >正文

duckdb使用详解

1. 下载安装

✅✅ 【方式 1:安装 DuckDB 命令行(CLI)——最推荐】

✅ 步骤 1:进入下载页面

官方 CLI 下载地址:

👉 https://duckdb.org/docs/installation

找到 Windows → Command Line Interface (CLI)
会看到类似文件:

duckdb_cli-windows-amd64.zip

也可以直接从 GitHub 下载最新版:

👉 https://github.com/duckdb/duckdb/releases

✅ 步骤 2:解压到任意目录,例如:

C:\Tools\duckdb\

解压后会有一个可执行文件:

duckdb.exe

✅ 步骤 3(可选):加入系统 PATH

C:\Tools\duckdb\ 加入 PATH:

  1. 右键 “此电脑” → 属性
  2. 高级系统设置 → 环境变量
  3. 编辑 Path → 添加 C:\Tools\duckdb\

✅ 加入 PATH 以后可以直接在命令行使用:

duckdb

就进入 DuckDB CLI:

v1.x.x  DuckDB CLI Enter ".help" for usage hints.

在这里插入图片描述

✔ 你可以执行 SQL
✔ 不需要启动数据库
✔ 不需要服务端

✅ ✅ 【方式 2:在 Docker 中使用】

docker run -it --rm ghcr.io/duckdb/duckdb:latest

适合容器环境。


✅ 如何判断安装成功?

在命令行输入:

duckdb

就进入 DuckDB CLI:

v1.x.x  DuckDB CLI Enter ".help" for usage hints.

2. 知识获取

✅ 1. 官方网站 和 文档

  • ✅ 官方网站:

https://duckdb.org/

  • ✅ 官方文档:

https://duckdb.org/docs/

  • ✅ GitHub (开源仓库):

https://github.com/duckdb/duckdb

  • ✅ Release 下载(Windows / macOS / Linux):

https://duckdb.org/docs/installation/

✅ 官方博客(技术文章、性能对比、优化原理):

https://duckdb.org/news/

在这里插入图片描述

✅ 2. DuckDB 的社区与生态

  • 开发团队主要来自奥地利与荷兰的数据库研究人员

  • 商业公司:DuckDB Labs 提供专业支持

  • GitHub Star 数非常高,增长速度快

  • 已被大量数据科学、BI、数据工程、机器学习社区采用

  • 集成度很高:可以在 Python、R、Node.js、Go、C++、Rust、Java 中使用

  • PowerBI、Tableau、Superset 等 BI 工具开始支持

  • 云数据平台(Snowflake、Databricks)也在研究支持 DuckDB 格式的查询

3. 基本功能能力(不结合数据)

✅ ✅ (1)无需部署,开箱即用

下载一个 duckdb 可执行文件就能运行:

duckdb SELECT 1;

不需要服务、不需要端口、不需要 root 权限。

在这里插入图片描述


✅ ✅ (2)支持完整 SQL 查询

  • SELECT / JOIN / GROUP BY / HAVING

  • CTE、窗口函数、聚合函数

  • 子查询、视图、索引

它是完整 SQL 语义,而不是简化版。


✅ ✅ (3)列式存储 + 向量化执行引擎

  • 扫描速度快

  • 聚合、排序、分组性能优秀

  • 和大数据分析引擎(ClickHouse、Spark)实现方式类似

  • 单机即可处理数百万、上亿行数据

✅ ✅ (4)可以直接读取多种数据源(无需导入)

文件格式支持?
CSV
Parquet
JSON
Excel(需扩展)
Arrow
SQLite 表
PostgreSQL 表

不需要 “导入到数据库” 再查询,直接查询文件本身。

✅ (5)一句话总结

DuckDB = 专门为本地数据分析准备的小型列式数据仓库

无需服务端、支持 SQL、快、支持 CSV/Parquet/Excel、开源免费。

4. 结合实际数据我们来做几个样例

4.1. 使用python生成数据

4.1.1. 生成数据代码

conda install xlsxwriter
# Generate a realistic random sales dataset for DuckDB demos
import pandas as pd
import numpy as np
from datetime import datetime, timedelta
import random
import os# ====== 配置文件路径 ======
xlsx_path = r"F:\Data\sales_sample.xlsx"
csv_path = r"F:\Data\sales_sample.csv"# 如果文件夹不存在,自动创建
os.makedirs(os.path.dirname(xlsx_path), exist_ok=True)np.random.seed(42)
random.seed(42)# Config
N = 10000  # number of order rows
start_date = datetime(2024, 1, 1)
end_date = datetime(2025, 11, 1)
days_range = (end_date - start_date).daysregions = ["华东","华南","华北","华中","西南","西北","东北"]
channels = ["Web","App","门店","电销","经销商"]
payment_methods = ["支付宝","微信支付","银联","现金","刷卡"]
categories = {"手机数码":["手机","平板","耳机","智能手表","相机"],"家居家电":["空调","洗衣机","电冰箱","扫地机器人","净水器"],"生鲜食品":["牛奶","鸡蛋","苹果","三文鱼","牛排"],"服装鞋帽":["T恤","牛仔裤","运动鞋","外套","连衣裙"],"办公用品":["打印机","墨盒","A4纸","订书机","显示器"]
}
category_names = list(categories.keys())# Make a tiny customer dimension
cust_n = 500
customer_ids = [f"C{str(i).zfill(5)}" for i in range(1, cust_n+1)]
cities = ["北京","上海","广州","深圳","杭州","成都","武汉","西安","南京","苏州","长沙","青岛"]
vip_levels = ["普通","银卡","金卡","白金"]customers = pd.DataFrame({"customer_id": customer_ids,"name": [f"用户{np.random.randint(100000,999999)}" for _ in range(cust_n)],"city": np.random.choice(cities, size=cust_n, replace=True),"vip_level": np.random.choice(vip_levels, size=cust_n, replace=True, p=[0.55,0.25,0.15,0.05]),"signup_date": [start_date + timedelta(days=int(np.random.rand()*days_range)) for _ in range(cust_n)],
})# Generate orders
order_ids = [f"O{str(i).zfill(7)}" for i in range(1, N+1)]
order_dates = [start_date + timedelta(days=int(np.random.rand()*days_range)) for _ in range(N)]
customer_pick = np.random.choice(customer_ids, size=N, replace=True)
region_pick = np.random.choice(regions, size=N, replace=True)
channel_pick = np.random.choice(channels, size=N, replace=True)cat_pick = np.random.choice(category_names, size=N, replace=True)
prod_pick = [np.random.choice(categories[c]) for c in cat_pick]# Unit prices
base_price = {"手机数码": (300, 8000),"家居家电": (500, 10000),"生鲜食品": (5, 200),"服装鞋帽": (30, 1200),"办公用品": (10, 5000)
}
unit_prices = [round(np.random.lognormal(mean=np.log((base_price[c][0]+base_price[c][1])/2), sigma=0.6), 2)for c in cat_pick
]# Clamp
for i, c in enumerate(cat_pick):mn, mx = base_price[c]unit_prices[i] = float(np.clip(unit_prices[i], mn, mx))qty = np.random.randint(1, 6, size=N)
bulk_idx = np.random.choice(np.arange(N), size=int(0.02*N), replace=False)
qty[bulk_idx] = np.random.randint(6, 50, size=bulk_idx.size)discount = np.round(np.random.choice([0,0.05,0.1,0.15,0.2], size=N, p=[0.55,0.2,0.15,0.07,0.03]), 2)
payment_pick = np.random.choice(payment_methods, size=N, replace=True)# Missing values
nan_indices = np.random.choice(np.arange(N), size=int(0.015*N), replace=False)
payment_pick[nan_indices] = None
disc_nan_idx = np.random.choice(np.arange(N), size=int(0.01*N), replace=False)
discount[disc_nan_idx] = np.nanamount = np.round((np.array(unit_prices) * qty) * (1 - np.nan_to_num(discount, nan=0.0)), 2)orders = pd.DataFrame({"order_id": order_ids,"order_date": order_dates,"customer_id": customer_pick,"region": region_pick,"channel": channel_pick,"category": cat_pick,"product": prod_pick,"unit_price": unit_prices,"quantity": qty,"discount": discount,"amount": amount,"payment_method": payment_pick
})# Add anomalies
an_rows = np.random.choice(np.arange(N), size=10, replace=False)
orders.loc[an_rows[:5], "quantity"] = 0
orders.loc[an_rows[5:], "quantity"] = -np.random.randint(1, 5, size=5)outlier_idx = np.random.choice(np.arange(N), size=3, replace=False)
orders.loc[outlier_idx, "unit_price"] *= 50dup_idx = np.random.choice(np.arange(N), size=5, replace=False)
dups = orders.iloc[dup_idx].copy()
orders_with_dups = pd.concat([orders, dups], ignore_index=True)# Save to XLSX and CSV
with pd.ExcelWriter(xlsx_path, engine="xlsxwriter") as writer:orders_with_dups.to_excel(writer, sheet_name="orders", index=False)customers.to_excel(writer, sheet_name="customers", index=False)orders_with_dups.to_csv(csv_path, index=False, encoding="utf-8-sig")print("✅ 已生成:")
print("Excel:", xlsx_path)
print("CSV:", csv_path)

4.1.2. 生成数据信息介绍

4.1.2.1.✅ 数据集说明:sales_sample(示例销售数据集)

该脚本自动生成一个模拟的真实销售业务数据集,包含两张表:

订单事实表:orders(约 10,005 行,其中含 5 条重复)
客户维表:customers(500 名客户)

数据内容涵盖地区、渠道、商品分类、支付方式、折扣、金额、多种异常数据等,非常适合:

  • DuckDB / SQL / 数据仓库教程

  • 数据清洗与异常检测案例

  • 数据分析、报表、BI 测试

  • ETL 转换、Parquet 导出、数据湖演示

  • Pandas 与 DuckDB 性能对比案例


✅ 一、订单表:orders(sheet: orders)
字段名类型说明
order_id字符串 (如 O0000001)每条订单唯一编号,格式化为 7 位递增编号
order_date日期订单发生时间,介于 2024-01-01 ~ 2025-11-01 随机分布
customer_id字符串 (如 C00001)购买用户,与 customers 表关联
region枚举华东、华南、华北、华中、西南、西北、东北
channel枚举Web、App、门店、电销、经销商
category枚举手机数码、家居家电、生鲜食品、服装鞋帽、办公用品
product商品名称如:手机、显示器、打印机、耳机、苹果、空调…
unit_price单价按分类定价区间内随机生成,含价格异常值
quantity数量正常范围 1~5,但有异常数量(0 或负数)
discount折扣率0、5%、10%、15%、20%,部分为空缺
amount实付金额(单价 × 数量 × (1-折扣)),含异常数据
payment_method支付方式支付宝、微信支付、银联、现金、刷卡,部分缺失值

✅ 订单量与数据特点

  • 总订单数:10,000 行 + 5 条重复 = 10,005 行
  • 跨 22 个月随机分布,具备季节性分析可能
  • 支持区域 / 渠道 / 品类 / 商品粒度分析
  • 金额范围真实,适合做交易额 / GMV 分析

✅ 二、客户表:customers(sheet: customers)
字段名说明
customer_id主键,C00001~C00500
name随机中文用户名,如“用户123456”
city一线/新一线主要城市
vip_level普通、银卡、金卡、白金(含概率分布)
signup_date注册时间,分布同订单时间段

4.2. 使用duckdb统计数据

DuckDB 支持完整 SQL,可轻松针对订单数据进行基础经营分析:

  • 总订单数(Orders)
  • 总销售额(GMV / Revenue)
  • 平均客单价(AOV / Avg Order Value)
  • 总销量、交易笔数、毛利模拟
  • 用户数量、下单人数

4.2.1. 加载数据

4.2.1.1 加载csv
PS C:\Users\caimingyang> duckdb
DuckDB v1.4.1 (Andium) b390a7c376
Enter ".help" for usage hints.
Connected to a transient in-memory database.
Use ".open FILENAME" to reopen on a persistent database.D SELECT * FROM read_csv_auto('F:/Data/sales_sample.csv') LIMIT 10;
┌──────────┬────────────┬─────────────┬─────────┬─────────┬───┬──────────┬──────────┬──────────┬────────────────┐
│ order_id │ order_date │ customer_id │ region  │ channel │ … │ quantity │ discount │  amount  │ payment_method │
│ varchar  │    date    │   varchar   │ varchar │ varchar │   │  int64   │  double  │  double  │    varchar     │
├──────────┼────────────┼─────────────┼─────────┼─────────┼───┼──────────┼──────────┼──────────┼────────────────┤
│ O0000001 │ 2024-04-24 │ C00466      │ 华南    │ App     │ … │        3 │      0.1 │ 12411.95 │ 现金           │
│ O0000002 │ 2024-10-01 │ C00288      │ 华南    │ 门店    │ … │        5 │      0.1 │  5310.04 │ 支付宝         │
│ O0000003 │ 2024-10-10 │ C00353      │ 东北    │ 门店    │ … │        4 │     0.05 │ 18798.87 │ 支付宝         │
│ O0000004 │ 2025-07-04 │ C00164      │ 华北    │ 电销    │ … │        1 │      0.0 │   105.43 │ 刷卡           │
│ O0000005 │ 2024-01-01 │ C00412      │ 西南    │ App     │ … │        2 │     0.05 │  15200.0 │ 银联           │
│ O0000006 │ 2024-07-20 │ C00400      │ 华北    │ 电销    │ … │        4 │      0.0 │   392.76 │ 现金           │
│ O0000007 │ 2025-10-19 │ C00016      │ 华中    │ App     │ … │        1 │      0.1 │   174.32 │ 支付宝         │
│ O0000008 │ 2024-11-14 │ C00018      │ 东北    │ 门店    │ … │        4 │      0.0 │ 10442.36 │ 现金           │
│ O0000009 │ 2024-09-13 │ C00136      │ 西北    │ 电销    │ … │        4 │      0.1 │ 18960.01 │ 刷卡           │
│ O0000010 │ 2024-03-21 │ C00490      │ 东北    │ App     │ … │        2 │     0.05 │  3060.25 │ 刷卡           │
├──────────┴────────────┴─────────────┴─────────┴─────────┴───┴──────────┴──────────┴──────────┴────────────────┤
│ 10 rows                                                                                  12 columns (9 shown) │
└───────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
D
4.2.1.2. 加载excel

直接运行加载会报错

D SELECT * FROM read_csv_auto('F:/Data/sales_sample.xlsx') LIMIT 10;
Invalid Input Error:
Error when sniffing file "F:/Data/sales_sample.xlsx".
It was not possible to automatically detect the CSV parsing dialect
The search space used was:
Delimiter Candidates: ',', '|', ';', '  '
Quote/Escape Candidates: ['(no quote)','(no escape)'],['"','(no escape)'],['"','"'],['"','''],['"','\'],[''','(no escape)'],[''','''],[''','"'],[''','\']
Comment Candidates: '\0', '#'
Encoding: utf-8
Possible fixes:
* Disable the parser's strict mode (strict_mode=false) to allow reading rows that do not comply with the CSV standard.
* Make sure you are using the correct file encoding. If not, set it (e.g., encoding = 'utf-16').
* Set delimiter (e.g., delim=',')
* Set quote (e.g., quote='"')
* Set escape (e.g., escape='"')
* Set comment (e.g., comment='#')
* Set skip (skip=${n}) to skip ${n} lines at the top of the file
* Enable ignore errors (ignore_errors=true) to ignore potential errors
* Enable null padding (null_padding=true) to pad missing columns with NULL values
* Check you are using the correct file compression, otherwise set it (e.g., compression = 'zstd')
* Be sure that the maximum line size is set to an appropriate value, otherwise set it (e.g., max_line_size=10000000)LINE 1: SELECT * FROM read_csv_auto('F:/Data/sales_sample.xlsx') LIMIT 10;

安装插件

INSTALL 'excel';
LOAD 'excel';

读取excel

D SELECT * FROM read_xlsx('F:/Data/sales_sample.xlsx', sheet = 'orders');
┌──────────┬─────────────────────┬─────────────┬─────────┬───┬──────────┬──────────┬──────────┬────────────────┐
│ order_id │     order_date      │ customer_id │ region  │ … │ quantity │ discount │  amount  │ payment_method │
│ varchar  │      timestamp      │   varchar   │ varchar │   │  double  │  double  │  double  │    varchar     │
├──────────┼─────────────────────┼─────────────┼─────────┼───┼──────────┼──────────┼──────────┼────────────────┤
│ O0000001 │ 2024-04-24 00:00:00 │ C00466      │ 华南    │ … │      3.00.112411.95 │ 现金           │
│ O0000002 │ 2024-10-01 00:00:00 │ C00288      │ 华南    │ … │      5.00.15310.04 │ 支付宝         │
│ O0000003 │ 2024-10-10 00:00:00 │ C00353      │ 东北    │ … │      4.00.0518798.87 │ 支付宝         │
│ O0000004 │ 2025-07-04 00:00:00 │ C00164      │ 华北    │ … │      1.00.0105.43 │ 刷卡           │
│ O0000005 │ 2024-01-01 00:00:00 │ C00412      │ 西南    │ … │      2.00.0515200.0 │ 银联           │
│ O0000006 │ 2024-07-20 00:00:00 │ C00400      │ 华北    │ … │      4.00.0392.76 │ 现金           │
│ O0000007 │ 2025-10-19 00:00:00 │ C00016      │ 华中    │ … │      1.00.1174.32 │ 支付宝         │
│ O0000008 │ 2024-11-14 00:00:00 │ C00018      │ 东北    │ … │      4.00.010442.36 │ 现金           │
│ O0000009 │ 2024-09-13 00:00:00 │ C00136      │ 西北    │ … │      4.00.118960.01 │ 刷卡           │
│ O0000010 │ 2024-03-21 00:00:00 │ C00490      │ 东北    │ … │      2.00.053060.25 │ 刷卡           │
│ O0000011 │ 2025-10-14 00:00:00 │ C00464      │ 华东    │ … │     22.00.019029.34 │ 银联           │
│ O0000012 │ 2024-01-14 00:00:00 │ C00247      │ 华北    │ … │      4.00.0538000.0 │ 银联           │
│ O0000013 │ 2025-05-08 00:00:00 │ C00248      │ 华南    │ … │      4.00.032000.0 │ 刷卡           │
│ O0000014 │ 2025-05-29 00:00:00 │ C00331      │ 华南    │ … │      3.00.0947.34 │ 微信支付       │
│ O0000015 │ 2024-06-12 00:00:00 │ C00198      │ 华中    │ … │      1.00.1198.68 │ 微信支付       │
│ O0000016 │ 2025-03-25 00:00:00 │ C00001      │ 西南    │ … │      5.00.015696.5 │ 支付宝         │
│ O0000017 │ 2024-03-03 00:00:00 │ C00190      │ 华东    │ … │      5.00.0510281.04 │ 银联           │
│ O0000018 │ 2024-06-21 00:00:00 │ C00381      │ 华北    │ … │      3.00.058987.42 │ 支付宝         │
│ O0000019 │ 2025-06-11 00:00:00 │ C00460      │ 西南    │ … │      4.00.136000.0 │ 现金           │
│ O0000020 │ 2025-08-02 00:00:00 │ C00294      │ 西南    │ … │      4.00.040000.0 │ 刷卡           │
│    ·     │          ·          │   ·         │  ·      │ · │       ·  │       ·  │      ·   │  ·             │
│    ·     │          ·          │   ·         │  ·      │ · │       ·  │       ·  │      ·   │  ·             │
│    ·     │          ·          │   ·         │  ·      │ · │       ·  │       ·  │      ·   │  ·             │
│ O0009986 │ 2025-07-10 00:00:00 │ C00221      │ 华南    │ … │      3.00.05570.0 │ 微信支付       │
│ O0009987 │ 2025-06-19 00:00:00 │ C00109      │ 华东    │ … │      2.00.03572.32 │ 现金           │
│ O0009988 │ 2024-08-30 00:00:00 │ C00027      │ 华中    │ … │      3.00.010073.76 │ 支付宝         │
│ O0009989 │ 2024-05-25 00:00:00 │ C00246      │ 西南    │ … │      5.00.028842.9 │ 现金           │
│ O0009990 │ 2025-09-14 00:00:00 │ C00055      │ 东北    │ … │      5.00.0517410.22 │ 微信支付       │
│ O0009991 │ 2024-07-24 00:00:00 │ C00465      │ 华东    │ … │      1.00.01317.38 │ 刷卡           │
│ O0009992 │ 2024-09-23 00:00:00 │ C00133      │ 华东    │ … │      4.00.032000.0 │ 微信支付       │
│ O0009993 │ 2025-04-13 00:00:00 │ C00052      │ 华东    │ … │      4.00.01703.56 │ 银联           │
│ O0009994 │ 2024-07-15 00:00:00 │ C00493      │ 华中    │ … │      5.00.05720.58 │ 刷卡           │
│ O0009995 │ 2025-07-02 00:00:00 │ C00253      │ 华北    │ … │      4.00.0257.92 │ 支付宝         │
│ O0009996 │ 2024-02-16 00:00:00 │ C00269      │ 西北    │ … │      4.00.04800.0 │ 现金           │
│ O0009997 │ 2025-06-14 00:00:00 │ C00298      │ 东北    │ … │      1.00.01141.6 │ 刷卡           │
│ O0009998 │ 2025-02-07 00:00:00 │ C00399      │ 华东    │ … │      3.00.0573.15 │ 刷卡           │
│ O0009999 │ 2025-01-18 00:00:00 │ C00079      │ 西南    │ … │      3.00.059310.84 │ 银联           │
│ O0010000 │ 2024-11-03 00:00:00 │ C00018      │ 西南    │ … │      2.00.054251.16 │ 支付宝         │
│ O0004695 │ 2025-04-19 00:00:00 │ C00430      │ 西南    │ … │      2.00.06496.86 │ 微信支付       │
│ O0000221 │ 2025-03-28 00:00:00 │ C00211      │ 华东    │ … │      1.00.171.16 │ 微信支付       │
│ O0002140 │ 2024-04-01 00:00:00 │ C00069      │ 华东    │ … │      2.00.23225.97 │ 现金           │
│ O0004602 │ 2024-02-17 00:00:00 │ C00095      │ 华南    │ … │      1.00.03934.85 │ 刷卡           │
│ O0007509 │ 2025-01-28 00:00:00 │ C00465      │ 东北    │ … │      3.00.02393.52 │ 支付宝         │
├──────────┴─────────────────────┴─────────────┴─────────┴───┴──────────┴──────────┴──────────┴────────────────┤
│ 10005 rows (40 shown)                                                                   12 columns (8 shown) │
└──────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
D SELECT * FROM read_xlsx('F:/Data/sales_sample.xlsx', sheet = 'customers');
┌─────────────┬────────────┬─────────┬───────────┬─────────────────────┐
│ customer_id │    name    │  city   │ vip_level │     signup_date     │
│   varchar   │  varchar   │ varchar │  varchar  │      timestamp      │
├─────────────┼────────────┼─────────┼───────────┼─────────────────────┤
│ C00001      │ 用户221958 │ 深圳    │ 银卡      │ 2024-07-07 00:00:00 │
│ C00002      │ 用户771155 │ 苏州    │ 普通      │ 2024-06-18 00:00:00 │
│ C00003      │ 用户231932 │ 成都    │ 普通      │ 2024-01-04 00:00:00 │
│ C00004      │ 用户465838 │ 成都    │ 普通      │ 2025-04-11 00:00:00 │
│ C00005      │ 用户359178 │ 长沙    │ 银卡      │ 2024-02-02 00:00:00 │
│ C00006      │ 用户744167 │ 青岛    │ 金卡      │ 2024-12-22 00:00:00 │
│ C00007      │ 用户210268 │ 杭州    │ 银卡      │ 2025-10-06 00:00:00 │
│ C00008      │ 用户832180 │ 北京    │ 普通      │ 2024-03-14 00:00:00 │
│ C00009      │ 用户154886 │ 西安    │ 金卡      │ 2025-08-22 00:00:00 │
│ C00010      │ 用户237337 │ 杭州    │ 普通      │ 2025-10-26 00:00:00 │
│ C00011      │ 用户621430 │ 青岛    │ 普通      │ 2024-02-11 00:00:00 │
│ C00012      │ 用户187498 │ 青岛    │ 普通      │ 2025-08-14 00:00:00 │
│ C00013      │ 用户999159 │ 青岛    │ 银卡      │ 2024-12-11 00:00:00 │
│ C00014      │ 用户275203 │ 杭州    │ 普通      │ 2025-08-30 00:00:00 │
│ C00015      │ 用户291335 │ 武汉    │ 银卡      │ 2025-01-17 00:00:00 │
│ C00016      │ 用户378167 │ 深圳    │ 金卡      │ 2025-03-19 00:00:00 │
│ C00017      │ 用户141090 │ 成都    │ 普通      │ 2024-12-30 00:00:00 │
│ C00018      │ 用户429365 │ 深圳    │ 普通      │ 2025-08-02 00:00:00 │
│ C00019      │ 用户164820 │ 广州    │ 普通      │ 2025-05-06 00:00:00 │
│ C00020      │ 用户887201 │ 武汉    │ 普通      │ 2024-12-15 00:00:00 │
│   ·         │     ·      │  ·      │  ·        │          ·          │
│   ·         │     ·      │  ·      │  ·        │          ·          │
│   ·         │     ·      │  ·      │  ·        │          ·          │
│ C00481      │ 用户694319 │ 苏州    │ 普通      │ 2025-03-24 00:00:00 │
│ C00482      │ 用户584299 │ 南京    │ 普通      │ 2024-02-16 00:00:00 │
│ C00483      │ 用户712210 │ 南京    │ 白金      │ 2025-03-04 00:00:00 │
│ C00484      │ 用户548982 │ 成都    │ 金卡      │ 2024-06-30 00:00:00 │
│ C00485      │ 用户224046 │ 西安    │ 普通      │ 2025-02-01 00:00:00 │
│ C00486      │ 用户506619 │ 长沙    │ 银卡      │ 2025-03-31 00:00:00 │
│ C00487      │ 用户132097 │ 北京    │ 银卡      │ 2024-06-03 00:00:00 │
│ C00488      │ 用户766326 │ 苏州    │ 普通      │ 2024-11-02 00:00:00 │
│ C00489      │ 用户749150 │ 深圳    │ 金卡      │ 2024-05-07 00:00:00 │
│ C00490      │ 用户330229 │ 北京    │ 金卡      │ 2024-02-05 00:00:00 │
│ C00491      │ 用户218834 │ 西安    │ 普通      │ 2024-09-10 00:00:00 │
│ C00492      │ 用户193848 │ 北京    │ 普通      │ 2024-08-31 00:00:00 │
│ C00493      │ 用户152921 │ 广州    │ 普通      │ 2025-10-28 00:00:00 │
│ C00494      │ 用户805086 │ 深圳    │ 普通      │ 2024-10-26 00:00:00 │
│ C00495      │ 用户750429 │ 西安    │ 普通      │ 2024-08-11 00:00:00 │
│ C00496      │ 用户805660 │ 成都    │ 金卡      │ 2025-01-23 00:00:00 │
│ C00497      │ 用户384821 │ 苏州    │ 普通      │ 2024-02-29 00:00:00 │
│ C00498      │ 用户155609 │ 青岛    │ 普通      │ 2025-10-06 00:00:00 │
│ C00499      │ 用户327897 │ 武汉    │ 金卡      │ 2025-03-01 00:00:00 │
│ C00500      │ 用户131024 │ 西安    │ 银卡      │ 2025-05-20 00:00:00 │
├─────────────┴────────────┴─────────┴───────────┴─────────────────────┤
│ 500 rows (40 shown)                                        5 columns │
└──────────────────────────────────────────────────────────────────────┘

4.3. 增加扩展和查看扩展信息

✅ 1. 什么是 DuckDB 扩展?

DuckDB 是一个「核心非常小」的内嵌式数据库,默认只包含基础 SQL 与存储功能。
扩展(Extension) 就是给 DuckDB 动态增加额外能力:

例如:

扩展作用
excel读取 XLSX 文件(含 sheet 选择)
parquet高性能读取/写入 Parquet
jsonJSON 解析、查询、导入
icu更多国际化时间/字符处理
fts全文检索
sqlite_scanner直接读取 SQLite 文件
postgres_scanner查询 PostgreSQL 数据

DuckDB 的扩展就像插件,按需加载、可在线安装、无需重启。


✅ 2. 查看当前扩展信息

✅ 当前有哪些扩展可用?
D SELECT * FROM duckdb_extensions();
┌──────────────────┬─────────┬───────────┬──────────────────────┬──────────────────────────────────────────────────────────────────┬───────────────────┬───────────────────┬───────────────────┬────────────────┐
│  extension_name  │ loaded  │ installed │     install_path     │                           description                            │      aliases      │ extension_version │   install_mode    │ installed_from │
│     varcharbooleanbooleanvarcharvarcharvarchar[]varcharvarcharvarchar     │
├──────────────────┼─────────┼───────────┼──────────────────────┼──────────────────────────────────────────────────────────────────┼───────────────────┼───────────────────┼───────────────────┼────────────────┤
│ autocomplete     │ truetrue(BUILT-IN)           │ Adds support for autocomplete in the shell                       │ []                │ v1.4.1            │ STATICALLY_LINKED │                │
│ aws              │ falsefalse     │                      │ Provides features that depend on the AWS SDK                     │ []                │                   │ NOT_INSTALLED     │                │
│ azure            │ falsefalse     │                      │ Adds a filesystem abstraction for Azure blob storage to DuckDB   │ []                │                   │ NOT_INSTALLED     │                │
│ core_functions   │ truetrue(BUILT-IN)           │ Core function library                                            │ []                │ v1.4.1            │ STATICALLY_LINKED │                │
│ delta            │ falsefalse     │                      │ Adds support for Delta Lake                                      │ []                │                   │ NOT_INSTALLED     │                │
│ ducklake         │ falsefalse     │                      │ Adds support for DuckLake, SQL as a Lakehouse Format             │ []                │                   │ NOT_INSTALLED     │                │
│ encodings        │ falsefalse     │                      │ All unicode encodings to UTF-8[]                │                   │ NOT_INSTALLED     │                │
│ excel            │ truetrue      │ C:\Users\caimingya…  │ Adds support for Excel-like format strings                       │ []8504be9           │ REPOSITORY        │ core           │
│ fts              │ falsefalse     │                      │ Adds support for Full-Text Search Indexes                        │ []                │                   │ NOT_INSTALLED     │                │
│ httpfs           │ falsefalse     │                      │ Adds support for reading and writing files over a HTTP(S) conn…  │ [http, https, s3] │                   │ NOT_INSTALLED     │                │
│ iceberg          │ falsefalse     │                      │ Adds support for Apache Iceberg                                  │ []                │                   │ NOT_INSTALLED     │                │
│ icu              │ truetrue(BUILT-IN)           │ Adds support for time zones and collations using the ICU library │ []                │ v1.4.1            │ STATICALLY_LINKED │                │
│ inet             │ falsefalse     │                      │ Adds support for IP-related data types and functions             │ []                │                   │ NOT_INSTALLED     │                │
│ jemalloc         │ falsefalse     │                      │ Overwrites system allocator with JEMalloc                        │ []                │                   │ NOT_INSTALLED     │                │
│ json             │ truetrue(BUILT-IN)           │ Adds support for JSON operations                                 │ []                │ v1.4.1            │ STATICALLY_LINKED │                │
│ motherduck       │ falsefalse     │                      │ Enables motherduck integration with the system                   │ [md]              │                   │ NOT_INSTALLED     │                │
│ mysql_scanner    │ falsefalse     │                      │ Adds support for connecting to a MySQL database[mysql]           │                   │ NOT_INSTALLED     │                │
│ parquet          │ truetrue(BUILT-IN)           │ Adds support for reading and writing parquet files               │ []                │ v1.4.1            │ STATICALLY_LINKED │                │
│ postgres_scanner │ falsefalse     │                      │ Adds support for connecting to a Postgres database[postgres]        │                   │ NOT_INSTALLED     │                │
│ shell            │ truetrue(BUILT-IN)           │                                                                  │ []                │ v1.4.1            │ STATICALLY_LINKED │                │
│ spatial          │ falsefalse     │                      │ Geospatial extension that adds support for working with spatia…  │ []                │                   │ NOT_INSTALLED     │                │
│ sqlite_scanner   │ falsefalse     │                      │ Adds support for reading and writing SQLite database files       │ [sqlite, sqlite3] │                   │ NOT_INSTALLED     │                │
│ tpcds            │ falsefalse     │                      │ Adds TPC-DS data generation and query support                    │ []                │                   │ NOT_INSTALLED     │                │
│ tpch             │ falsefalse     │                      │ Adds TPC-H data generation and query support                     │ []                │                   │ NOT_INSTALLED     │                │
│ ui               │ falsefalse     │                      │ Adds local UI for DuckDB                                         │ []                │                   │ NOT_INSTALLED     │                │
│ vss              │ falsefalse     │                      │ Adds indexing support to accelerate Vector Similarity Search     │ []                │                   │ NOT_INSTALLED     │                │
├──────────────────┴─────────┴───────────┴──────────────────────┴──────────────────────────────────────────────────────────────────┴───────────────────┴───────────────────┴───────────────────┴────────────────┤
│ 26 rows                                                                                                                                                                                             9 columns │
└───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘

✅ 3. 安装扩展(INSTALL)

如果扩展没有安装,使用:

INSTALL 'excel';

或多个扩展:

INSTALL 'json', 'icu', 'postgres_scanner';

✅ 作用:下载扩展(本地缓存或从 DuckDB 仓库自动获取)
✅ 执行一次即可,下次不需要再 INSTALL


✅ 4. 加载扩展(LOAD)

扩展安装完成后需要 LOAD 才能使用:

LOAD 'excel';

或多个:

LOAD 'parquet', 'json';

✅ 执行后才会注册扩展里的函数,比如 read_xlsxread_jsonread_parquet
✅ 加载后立刻生效,无需重启


✅ 5. 自动加载扩展

如果希望数据库启动时自动加载某扩展:

SET autoload_extensions = 'excel, json, parquet';

或永久写入配置(在文件驱动方式)


✅ 6. 卸载扩展(UNLOAD)

如果你已加载扩展但想卸载:

UNLOAD 'excel';

✅ 卸载后扩展提供的函数不可用
✅ 数据库不会崩溃,动态卸载安全


✅ 7. 删除扩展(UNINSTALL)

删除本地已安装扩展:

UNINSTALL 'excel';

✅ 会从本地插件目录删除扩展对象,如 .duckdb/extensions/excel.duckdb_extension
✅ 之后如需使用必须重新 INSTALL


✅ 8. 扩展存放位置

Windows / Linux / macOS 通常默认存放在:

~/.duckdb/extensions/

或者数据库本地目录,取决于运行模式。


✅ 9. 列举常用扩展及用途

扩展用途
parquet读写 Parquet,超高性能列式格式
excel读 Excel,支持 sheet、范围、类型推断
jsonJSON 查询、导入、解析
icu国际化字符、日期、时区函数
fts全文检索(Full Text Search)
httpfs访问 HTTP/HTTPS、S3、Azure、GCS 存储
sqlite_scanner直接查询 SQLite 文件
postgres_scanner查询 PostgreSQL 数据库(零复制)
mysql_scanner查询 MySQL 数据库
delta读取 Delta Lake
spatial空间地理数据,GIS 类功能(如 PostGIS)
tpcds / tpchTPC 数据生成与测试(性能基准)

很多功能(比如 parquet / json)在部分构建中是静态内置的,不需要安装。

✅ 10. 一句话总结

  • INSTALL = 下载扩展
  • LOAD = 启动扩展
  • UNLOAD = 停用扩展
  • UNINSTALL = 删除扩展

DuckDB 的扩展系统让它从一个精简 SQL 引擎变成一个 本地小型数据分析平台

4.4. 将数据存储到duckdb中

D CREATE OR REPLACE TABLE orders AS
路 SELECT *
路 FROM read_xlsx('F:/Data/sales_sample.xlsx', sheet='orders');
D
D -- 建 customers 表
D CREATE OR REPLACE TABLE customers AS
路 SELECT *
路 FROM read_xlsx('F:/Data/sales_sample.xlsx', sheet='customers');
D
D SELECT 'orders' AS tbl, COUNT(*) AS rows FROM orders
路 UNION ALL
路 SELECT 'customers', COUNT(*) FROM customers;
┌───────────┬───────┐
│    tbl    │ rows  │
│  varchar  │ int64 │
├───────────┼───────┤
│ orders    │ 10005 │
│ customers │   500 │
└───────────┴───────┘
D
D DESCRIBE orders;
┌────────────────┬─────────────┬─────────┬─────────┬─────────┬─────────┐
│  column_name   │ column_type │  null   │   key   │ default │  extra  │
│    varchar     │   varchar   │ varchar │ varchar │ varchar │ varchar │
├────────────────┼─────────────┼─────────┼─────────┼─────────┼─────────┤
│ order_id       │ VARCHAR     │ YES     │ NULL    │ NULL    │ NULL    │
│ order_date     │ TIMESTAMP   │ YES     │ NULL    │ NULL    │ NULL    │
│ customer_id    │ VARCHAR     │ YES     │ NULL    │ NULL    │ NULL    │
│ region         │ VARCHAR     │ YES     │ NULL    │ NULL    │ NULL    │
│ channel        │ VARCHAR     │ YES     │ NULL    │ NULL    │ NULL    │
│ category       │ VARCHAR     │ YES     │ NULL    │ NULL    │ NULL    │
│ product        │ VARCHAR     │ YES     │ NULL    │ NULL    │ NULL    │
│ unit_price     │ DOUBLE      │ YES     │ NULL    │ NULL    │ NULL    │
│ quantity       │ DOUBLE      │ YES     │ NULL    │ NULL    │ NULL    │
│ discount       │ DOUBLE      │ YES     │ NULL    │ NULL    │ NULL    │
│ amount         │ DOUBLE      │ YES     │ NULL    │ NULL    │ NULL    │
│ payment_method │ VARCHAR     │ YES     │ NULL    │ NULL    │ NULL    │
├────────────────┴─────────────┴─────────┴─────────┴─────────┴─────────┤
│ 12 rows                                                    6 columns │
└──────────────────────────────────────────────────────────────────────┘
D DESCRIBE customers;
┌─────────────┬─────────────┬─────────┬─────────┬─────────┬─────────┐
│ column_name │ column_type │  null   │   key   │ default │  extra  │
│   varchar   │   varchar   │ varchar │ varchar │ varchar │ varchar │
├─────────────┼─────────────┼─────────┼─────────┼─────────┼─────────┤
│ customer_id │ VARCHAR     │ YES     │ NULL    │ NULL    │ NULL    │
│ name        │ VARCHAR     │ YES     │ NULL    │ NULL    │ NULL    │
│ city        │ VARCHAR     │ YES     │ NULL    │ NULL    │ NULL    │
│ vip_level   │ VARCHAR     │ YES     │ NULL    │ NULL    │ NULL    │
│ signup_date │ TIMESTAMP   │ YES     │ NULL    │ NULL    │ NULL    │
└─────────────┴─────────────┴─────────┴─────────┴─────────┴─────────┘
D
D SELECT * FROM orders    LIMIT 5;
┌──────────┬─────────────────────┬─────────────┬─────────┬─────────┬──────────┬──────────┬────────────┬──────────┬──────────┬──────────┬────────────────┐
│ order_id │     order_date      │ customer_id │ region  │ channel │ category │ product  │ unit_price │ quantity │ discount │  amount  │ payment_method │
│ varchar  │      timestamp      │   varchar   │ varchar │ varchar │ varchar  │ varchar  │   double   │  double  │  double  │  double  │    varchar     │
├──────────┼─────────────────────┼─────────────┼─────────┼─────────┼──────────┼──────────┼────────────┼──────────┼──────────┼──────────┼────────────────┤
│ O0000001 │ 2024-04-24 00:00:00 │ C00466      │ 华南    │ App     │ 手机数码 │ 相机     │    4597.023.00.112411.95 │ 现金           │
│ O0000002 │ 2024-10-01 00:00:00 │ C00288      │ 华南    │ 门店    │ 办公用品 │ 显示器   │    1180.015.00.15310.04 │ 支付宝         │
│ O0000003 │ 2024-10-10 00:00:00 │ C00353      │ 东北    │ 门店    │ 手机数码 │ 智能手表 │    4947.074.00.0518798.87 │ 支付宝         │
│ O0000004 │ 2025-07-04 00:00:00 │ C00164      │ 华北    │ 电销    │ 生鲜食品 │ 鸡蛋     │     105.431.00.0105.43 │ 刷卡           │
│ O0000005 │ 2024-01-01 00:00:00 │ C00412      │ 西南    │ App     │ 手机数码 │ 平板     │     8000.02.00.0515200.0 │ 银联           │
└──────────┴─────────────────────┴─────────────┴─────────┴─────────┴──────────┴──────────┴────────────┴──────────┴──────────┴──────────┴────────────────┘
D SELECT * FROM customers LIMIT 5;
┌─────────────┬────────────┬─────────┬───────────┬─────────────────────┐
│ customer_id │    name    │  city   │ vip_level │     signup_date     │
│   varchar   │  varchar   │ varchar │  varchar  │      timestamp      │
├─────────────┼────────────┼─────────┼───────────┼─────────────────────┤
│ C00001      │ 用户221958 │ 深圳    │ 银卡      │ 2024-07-07 00:00:00 │
│ C00002      │ 用户771155 │ 苏州    │ 普通      │ 2024-06-18 00:00:00 │
│ C00003      │ 用户231932 │ 成都    │ 普通      │ 2024-01-04 00:00:00 │
│ C00004      │ 用户465838 │ 成都    │ 普通      │ 2025-04-11 00:00:00 │
│ C00005      │ 用户359178 │ 长沙    │ 银卡      │ 2024-02-02 00:00:00 │
└─────────────┴────────────┴─────────┴───────────┴─────────────────────┘

4.5. 统计计算数据

4.5.1. 基础业务指标(KPI)

SELECTCOUNT(*)                                   AS total_orders,         -- 订单数SUM(amount)                                AS total_revenue,        -- 销售额AVG(amount)                                AS avg_order_value,      -- 平均客单价SUM(GREATEST(quantity,0))                  AS total_qty,            -- 总销量(负数/0按0计)COUNT_IF(amount > 0)                       AS paid_txn_cnt,         -- 交易笔数COUNT(DISTINCT customer_id)                AS buyers                -- 下单人数
FROM read_xlsx('F:/Data/sales_sample.xlsx', sheet='orders');
D SELECT COUNT(*) AS total_orders,SUM(amount) AS total_revenue,AVG(amount) AS avg_order_value,SUM(GREATEST(quantity,0)) AS total_qty,COUNT_IF(amount > 0)AS paid_txn_cnt,COUNT(DISTINCT customer_id) AS buyers FROM orders;
┌──────────────┬───────────────────┬───────────────────┬───────────┬──────────────┬────────┐
│ total_orders │   total_revenue   │  avg_order_value  │ total_qty │ paid_txn_cnt │ buyers │
│    int64     │      doubledoubledouble   │    int128    │ int64  │
├──────────────┼───────────────────┼───────────────────┼───────────┼──────────────┼────────┤
│    1000594118663.729999579407.16279160415435252.010005500   │
└──────────────┴───────────────────┴───────────────────┴───────────┴──────────────┴────────┘
D SELECT COUNT(*) AS total_orders,SUM(amount) AS total_revenue,AVG(amount) AS avg_order_value,SUM(GREATEST(quantity,0)) AS total_qty,COUNT_IF(amount > 0)AS paid_txn_cnt,COUNT(DISTINCT customer_id) AS buyers FROM read_xlsx('F:/Data/sales_sample.xlsx', sheet='orders');
┌──────────────┬───────────────────┬───────────────────┬───────────┬──────────────┬────────┐
│ total_orders │   total_revenue   │  avg_order_value  │ total_qty │ paid_txn_cnt │ buyers │
│    int64     │      doubledoubledouble   │    int128    │ int64  │
├──────────────┼───────────────────┼───────────────────┼───────────┼──────────────┼────────┤
│    1000594118663.729999579407.16279160415435252.010005500   │
└──────────────┴───────────────────┴───────────────────┴───────────┴──────────────┴────────┘
D EXPLAIN ANALYZE SELECT COUNT(*) AS total_orders,SUM(amount) AS total_revenue,AVG(amount) AS avg_order_value,SUM(GREATEST(quantity,0)) AS total_qty,COUNT_IF(amount > 0)AS paid_txn_cnt,COUNT(DISTINCT customer_id) AS buyers FROM read_xlsx('F:/Data/sales_sample.xlsx', sheet='orders');
┌─────────────────────────────────────┐
│┌───────────────────────────────────┐│
││    Query Profiling Information    ││
│└───────────────────────────────────┘│
└─────────────────────────────────────┘
EXPLAIN ANALYZE SELECT COUNT(*) AS total_orders,SUM(amount) AS total_revenue,AVG(amount) AS avg_order_value,SUM(GREATEST(quantity,0)) AS total_qty,COUNT_IF(amount > 0)AS paid_txn_cnt,COUNT(DISTINCT customer_id) AS buyers FROM read_xlsx('F:/Data/sales_sample.xlsx', sheet='orders');
┌────────────────────────────────────────────────┐
│┌──────────────────────────────────────────────┐│
││              Total Time: 0.0569s             ││
│└──────────────────────────────────────────────┘│
└────────────────────────────────────────────────┘
┌───────────────────────────┐
│           QUERY           │
└─────────────┬─────────────┘
┌─────────────┴─────────────┐
│      EXPLAIN_ANALYZE      │
│    ────────────────────   │
│           0 rows          │
│          (0.00s)          │
└─────────────┬─────────────┘
┌─────────────┴─────────────┐
│    UNGROUPED_AGGREGATE    │
│    ────────────────────   │
│        Aggregates:        │
│        count_star()       │
│          sum(#0)          │avg(#1)          │sum(#2)          │
│        count_if(#3)       │count(DISTINCT #4)    │
│                           │
│           1 row           │
│          (0.00s)          │
└─────────────┬─────────────┘
┌─────────────┴─────────────┐
│         PROJECTION        │
│    ────────────────────   │
│           amount          │
│           amount          │
│  greatest(quantity, 0.0)  │
│       (amount > 0.0)      │
│        customer_id        │
│                           │
│        10,005 rows        │
│          (0.00s)          │
└─────────────┬─────────────┘
┌─────────────┴─────────────┐
│         PROJECTION        │
│    ────────────────────   │
│            #10            │#8            │#2            │
│                           │
│        10,005 rows        │
│          (0.00s)          │
└─────────────┬─────────────┘
┌─────────────┴─────────────┐
│         TABLE_SCAN        │
│    ────────────────────   │
│    Function: READ_XLSX    │
│                           │
│        10,005 rows        │
│          (0.04s)          │
└───────────────────────────┘
D EXPLAIN ANALYZE SELECT COUNT(*) AS total_orders,SUM(amount) AS total_revenue,AVG(amount) AS avg_order_value,SUM(GREATEST(quantity,0)) AS total_qty,COUNT_IF(amount > 0)AS paid_txn_cnt,COUNT(DISTINCT customer_id) AS buyers FROM orders;
┌─────────────────────────────────────┐
│┌───────────────────────────────────┐│
││    Query Profiling Information    ││
│└───────────────────────────────────┘│
└─────────────────────────────────────┘
EXPLAIN ANALYZE SELECT COUNT(*) AS total_orders,SUM(amount) AS total_revenue,AVG(amount) AS avg_order_value,SUM(GREATEST(quantity,0)) AS total_qty,COUNT_IF(amount > 0)AS paid_txn_cnt,COUNT(DISTINCT customer_id) AS buyers FROM orders;
┌────────────────────────────────────────────────┐
│┌──────────────────────────────────────────────┐│
││              Total Time: 0.0026s             ││
│└──────────────────────────────────────────────┘│
└────────────────────────────────────────────────┘
┌───────────────────────────┐
│           QUERY           │
└─────────────┬─────────────┘
┌─────────────┴─────────────┐
│      EXPLAIN_ANALYZE      │
│    ────────────────────   │
│           0 rows          │
│          (0.00s)          │
└─────────────┬─────────────┘
┌─────────────┴─────────────┐
│    UNGROUPED_AGGREGATE    │
│    ────────────────────   │
│        Aggregates:        │
│        count_star()       │
│          sum(#0)          │avg(#1)          │sum(#2)          │
│        count_if(#3)       │count(DISTINCT #4)    │
│                           │
│           1 row           │
│          (0.00s)          │
└─────────────┬─────────────┘
┌─────────────┴─────────────┐
│         PROJECTION        │
│    ────────────────────   │
│           amount          │
│           amount          │
│  greatest(quantity, 0.0)  │
│            true           │
│        customer_id        │
│                           │
│        10,005 rows        │
│          (0.00s)          │
└─────────────┬─────────────┘
┌─────────────┴─────────────┐
│         TABLE_SCAN        │
│    ────────────────────   │
│       Table: orders       │
│   Type: Sequential Scan   │
│                           │
│        Projections:       │
│           amount          │
│          quantity         │
│        customer_id        │
│                           │
│        10,005 rows        │
│          (0.00s)          │
└───────────────────────────┘

4.5.2. 分组维度分析(地区/渠道/品类/支付方式)

D SELECT region,COUNT(*) AS orders,SUM(amount) AS revenue,ROUND(AVG(amount),2) AS aov FROM read_xlsx('F:/Data/sales_sample.xlsx', sheet='orders') GROUP BY region ORDER BY revenue DESC;
┌─────────┬────────┬────────────────────┬─────────┐
│ region  │ orders │      revenue       │   aov   │
│ varchar │ int64  │       doubledouble  │
├─────────┼────────┼────────────────────┼─────────┤
│ 西南    │   150914943416.7000000099902.86 │
│ 华中    │   149114459096.1300000239697.58 │
│ 东北    │   145013836316.4900000119542.29 │
│ 西北    │   139212942988.7900000299298.12 │
│ 华东    │   141012763540.5700000049052.16 │
│ 华北    │   138212664126.8599999969163.62 │
│ 华南    │   137112509178.1899999949124.13 │
└─────────┴────────┴────────────────────┴─────────┘
D SELECT region,COUNT(*) AS orders,SUM(amount) AS revenue,ROUND(AVG(amount),2) AS aov FROM orders GROUP BY region ORDER BY revenue DESC;
┌─────────┬────────┬────────────────────┬─────────┐
│ region  │ orders │      revenue       │   aov   │
│ varchar │ int64  │       doubledouble  │
├─────────┼────────┼────────────────────┼─────────┤
│ 西南    │   150914943416.7000000099902.86 │
│ 华中    │   149114459096.1300000239697.58 │
│ 东北    │   145013836316.4900000119542.29 │
│ 西北    │   139212942988.7900000299298.12 │
│ 华东    │   141012763540.5700000049052.16 │
│ 华北    │   138212664126.8599999969163.62 │
│ 华南    │   137112509178.1899999949124.13 │
└─────────┴────────┴────────────────────┴─────────┘
D EXPLAIN ANALYZE SELECT region,COUNT(*) AS orders,SUM(amount) AS revenue,ROUND(AVG(amount),2) AS aov FROM read_xlsx('F:/Data/sales_sample.xlsx', sheet='orders') GROUP BY region ORDER BY revenue DESC;
┌─────────────────────────────────────┐
│┌───────────────────────────────────┐│
││    Query Profiling Information    ││
│└───────────────────────────────────┘│
└─────────────────────────────────────┘
EXPLAIN ANALYZE SELECT region,COUNT(*) AS orders,SUM(amount) AS revenue,ROUND(AVG(amount),2) AS aov FROM read_xlsx('F:/Data/sales_sample.xlsx', sheet='orders') GROUP BY region ORDER BY revenue DESC;
┌────────────────────────────────────────────────┐
│┌──────────────────────────────────────────────┐│
││              Total Time: 0.0899s             ││
│└──────────────────────────────────────────────┘│
└────────────────────────────────────────────────┘
┌───────────────────────────┐
│           QUERY           │
└─────────────┬─────────────┘
┌─────────────┴─────────────┐
│      EXPLAIN_ANALYZE      │
│    ────────────────────   │
│           0 rows          │
│          (0.00s)          │
└─────────────┬─────────────┘
┌─────────────┴─────────────┐
│          ORDER_BY         │
│    ────────────────────   │
│ sum(read_xlsx.amount) DESC│
│                           │
│           7 rows          │
│          (0.00s)          │
└─────────────┬─────────────┘
┌─────────────┴─────────────┐
│         PROJECTION        │
│    ────────────────────   │
│           region          │
│           orders          │
│          revenue          │
│            aov            │
│                           │
│           7 rows          │
│          (0.00s)          │
└─────────────┬─────────────┘
┌─────────────┴─────────────┐
│       HASH_GROUP_BY       │
│    ────────────────────   │
│         Groups: #0        │
│                           │
│        Aggregates:        │
│        count_star()       │
│          sum(#1)          │avg(#2)          │
│                           │
│           7 rows          │
│          (0.01s)          │
└─────────────┬─────────────┘
┌─────────────┴─────────────┐
│         PROJECTION        │
│    ────────────────────   │
│           region          │
│           amount          │
│           amount          │
│                           │
│        10,005 rows        │
│          (0.00s)          │
└─────────────┬─────────────┘
┌─────────────┴─────────────┐
│         PROJECTION        │
│    ────────────────────   │
│             #3            │#10            │
│                           │
│        10,005 rows        │
│          (0.00s)          │
└─────────────┬─────────────┘
┌─────────────┴─────────────┐
│         TABLE_SCAN        │
│    ────────────────────   │
│    Function: READ_XLSX    │
│                           │
│        10,005 rows        │
│          (0.07s)          │
└───────────────────────────┘
D
D EXPLAIN ANALYZE SELECT region,COUNT(*) AS orders,SUM(amount) AS revenue,ROUND(AVG(amount),2) AS aov FROM orders GROUP BY region ORDER BY revenue DESC;
┌─────────────────────────────────────┐
│┌───────────────────────────────────┐│
││    Query Profiling Information    ││
│└───────────────────────────────────┘│
└─────────────────────────────────────┘
EXPLAIN ANALYZE SELECT region,COUNT(*) AS orders,SUM(amount) AS revenue,ROUND(AVG(amount),2) AS aov FROM orders GROUP BY region ORDER BY revenue DESC;
┌────────────────────────────────────────────────┐
│┌──────────────────────────────────────────────┐│
││              Total Time: 0.0031s             ││
│└──────────────────────────────────────────────┘│
└────────────────────────────────────────────────┘
┌───────────────────────────┐
│           QUERY           │
└─────────────┬─────────────┘
┌─────────────┴─────────────┐
│      EXPLAIN_ANALYZE      │
│    ────────────────────   │
│           0 rows          │
│          (0.00s)          │
└─────────────┬─────────────┘
┌─────────────┴─────────────┐
│         PROJECTION        │
│    ────────────────────   │
│__internal_decompress_strin│
│           g(#0)           │#1            │#2            │#3            │
│                           │
│           7 rows          │
│          (0.00s)          │
└─────────────┬─────────────┘
┌─────────────┴─────────────┐
│          ORDER_BY         │
│    ────────────────────   │
│   sum(memory.main.orders  │
│       .amount) DESC       │
│                           │
│           7 rows          │
│          (0.00s)          │
└─────────────┬─────────────┘
┌─────────────┴─────────────┐
│         PROJECTION        │
│    ────────────────────   │
│__internal_compress_string_│
│        ubigint(#0)        │#1            │#2            │#3            │
│                           │
│           7 rows          │
│          (0.00s)          │
└─────────────┬─────────────┘
┌─────────────┴─────────────┐
│         PROJECTION        │
│    ────────────────────   │
│           region          │
│           orders          │
│          revenue          │
│            aov            │
│                           │
│           7 rows          │
│          (0.00s)          │
└─────────────┬─────────────┘
┌─────────────┴─────────────┐
│         PROJECTION        │
│    ────────────────────   │
│__internal_decompress_strin│
│           g(#0)           │#1            │#2            │#3            │
│                           │
│           7 rows          │
│          (0.00s)          │
└─────────────┬─────────────┘
┌─────────────┴─────────────┐
│       HASH_GROUP_BY       │
│    ────────────────────   │
│         Groups: #0        │
│                           │
│        Aggregates:        │
│        count_star()       │
│          sum(#1)          │avg(#2)          │
│                           │
│           7 rows          │
│          (0.00s)          │
└─────────────┬─────────────┘
┌─────────────┴─────────────┐
│         PROJECTION        │
│    ────────────────────   │
│           region          │
│           amount          │
│           amount          │
│                           │
│        10,005 rows        │
│          (0.00s)          │
└─────────────┬─────────────┘
┌─────────────┴─────────────┐
│         PROJECTION        │
│    ────────────────────   │
│__internal_compress_string_│
│        ubigint(#0)        │#1            │
│                           │
│        10,005 rows        │
│          (0.00s)          │
└─────────────┬─────────────┘
┌─────────────┴─────────────┐
│         TABLE_SCAN        │
│    ────────────────────   │
│       Table: orders       │
│   Type: Sequential Scan   │
│                           │
│        Projections:       │
│           region          │
│           amount          │
│                           │
│        10,005 rows        │
│          (0.00s)          │
└───────────────────────────┘

4.5.2. 新客 vs 老客(定义:用户在其“首单当月”为新客)

D EXPLAIN ANALYZEWITH first_order AS (SELECT
路     customer_id,MIN(order_date) AS first_dt
路   FROM orders
路   GROUP BY customer_id
路 ),
路 labeled AS (SELECT
路     o.*,CASE WHEN date_trunc('month', o.order_date) = date_trunc('month', f.first_dt)THEN '新客'ELSE '老客'END AS cust_tag
路   FROM orders o
路   JOIN first_order f USING (customer_id))SELECT
路   cust_tag,COUNT(*)             AS orders,COUNT(DISTINCT customer_id) AS buyers,SUM(amount)          AS revenue,ROUND(AVG(amount),2) AS aov
路 FROM labeled
路 GROUP BY cust_tag
路 ORDER BY revenue DESC;
┌─────────────────────────────────────┐
│┌───────────────────────────────────┐│
││    Query Profiling Information    ││
│└───────────────────────────────────┘│
└─────────────────────────────────────┘
EXPLAIN ANALYZE  WITH first_order AS (   SELECT     customer_id,     MIN(order_date) AS first_dt   FROM orders   GROUP BY customer_id ), labeled AS (   SELECT     o.*,     CASE WHEN date_trunc('month', o.order_date) = date_trunc('month', f.first_dt)          THEN '新客'          ELSE '老客'     END AS cust_tag   FROM orders o   JOIN first_order f USING (customer_id) ) SELECT   cust_tag,   COUNT(*)             AS orders,   COUNT(DISTINCT customer_id) AS buyers,   SUM(amount)          AS revenue,   ROUND(AVG(amount),2) AS aov FROM labeled GROUP BY cust_tag ORDER BY revenue DESC;
┌────────────────────────────────────────────────┐
│┌──────────────────────────────────────────────┐│
││              Total Time: 0.0117s             ││
│└──────────────────────────────────────────────┘│
└────────────────────────────────────────────────┘
┌───────────────────────────┐
│           QUERY           │
└─────────────┬─────────────┘
┌─────────────┴─────────────┐
│      EXPLAIN_ANALYZE      │
│    ────────────────────   │
│           0 rows          │
│          (0.00s)          │
└─────────────┬─────────────┘
┌─────────────┴─────────────┐
│         PROJECTION        │
│    ────────────────────   │
│__internal_decompress_strin│
│           g(#0)           │#1            │#2            │#3            │#4            │
│                           │
│           2 rows          │
│          (0.00s)          │
└─────────────┬─────────────┘
┌─────────────┴─────────────┐
│          ORDER_BY         │
│    ────────────────────   │
│  sum(labeled.amount) DESC │
│                           │
│           2 rows          │
│          (0.00s)          │
└─────────────┬─────────────┘
┌─────────────┴─────────────┐
│         PROJECTION        │
│    ────────────────────   │
│__internal_compress_string_│
│        ubigint(#0)        │#1            │#2            │#3            │#4            │
│                           │
│           2 rows          │
│          (0.00s)          │
└─────────────┬─────────────┘
┌─────────────┴─────────────┐
│         PROJECTION        │
│    ────────────────────   │
│          cust_tag         │
│           orders          │
│           buyers          │
│          revenue          │
│            aov            │
│                           │
│           2 rows          │
│          (0.00s)          │
└─────────────┬─────────────┘
┌─────────────┴─────────────┐
│         PROJECTION        │
│    ────────────────────   │
│__internal_decompress_strin│
│           g(#0)           │#1            │#2            │#3            │#4            │
│                           │
│           2 rows          │
│          (0.00s)          │
└─────────────┬─────────────┘
┌─────────────┴─────────────┐
│       HASH_GROUP_BY       │
│    ────────────────────   │
│         Groups: #0        │
│                           │
│        Aggregates:        │
│        count_star()       │
│     count(DISTINCT #1)    │sum(#2)          │avg(#3)          │
│                           │
│           2 rows          │
│          (0.01s)          │
└─────────────┬─────────────┘
┌─────────────┴─────────────┐
│         PROJECTION        │
│    ────────────────────   │
│          cust_tag         │
│        customer_id        │
│           amount          │
│           amount          │
│                           │
│        10,005 rows        │
│          (0.00s)          │
└─────────────┬─────────────┘
┌─────────────┴─────────────┐
│         PROJECTION        │
│    ────────────────────   │
│             #0            │#1            │
│__internal_compress_string_│
│        ubigint(#2)        │
│                           │
│        10,005 rows        │
│          (0.00s)          │
└─────────────┬─────────────┘
┌─────────────┴─────────────┐
│         PROJECTION        │
│    ────────────────────   │
│        customer_id        │
│           amount          │
│          cust_tag         │
│                           │
│        10,005 rows        │
│          (0.00s)          │
└─────────────┬─────────────┘
┌─────────────┴─────────────┐
│         HASH_JOIN         │
│    ────────────────────   │
│      Join Type: INNER     │
│                           │
│        Conditions:        ├──────────────┐
│ customer_id = customer_id │              │
│                           │              │
│        10,005 rows        │              │
│          (0.01s)          │              │
└─────────────┬─────────────┘              │
┌─────────────┴─────────────┐┌─────────────┴─────────────┐
│         TABLE_SCAN        ││         PROJECTION        │
│    ────────────────────   ││    ────────────────────   │
│       Table: orders       ││__internal_decompress_strin│
│   Type: Sequential Scan   ││           g(#0)           │
│                           ││             #1            │
│        Projections:       ││                           │
│        customer_id        ││                           │
│         order_date        ││                           │
│           amount          ││                           │
│                           ││                           │
│        10,005 rows        ││          500 rows         │
│          (0.00s)          ││          (0.00s)          │
└───────────────────────────┘└─────────────┬─────────────┘┌─────────────┴─────────────┐│       HASH_GROUP_BY       ││    ────────────────────   ││         Groups: #0        ││    Aggregates: min(#1)    ││                           ││          500 rows         ││          (0.01s)          │└─────────────┬─────────────┘┌─────────────┴─────────────┐│         PROJECTION        ││    ────────────────────   ││        customer_id        ││         order_date        ││                           ││        10,005 rows        ││          (0.00s)          │└─────────────┬─────────────┘┌─────────────┴─────────────┐│         PROJECTION        ││    ────────────────────   ││__internal_compress_string_││        ubigint(#0)        │#1            ││                           ││        10,005 rows        ││          (0.00s)          │└─────────────┬─────────────┘┌─────────────┴─────────────┐│         TABLE_SCAN        ││    ────────────────────   ││       Table: orders       ││   Type: Sequential Scan   ││                           ││        Projections:       ││        customer_id        ││         order_date        ││                           ││        10,005 rows        ││          (0.00s)          │└───────────────────────────┘
D
D
D
D EXPLAIN ANALYZEWITH first_order AS (SELECT
路     customer_id,MIN(order_date) AS first_dt
路   FROM read_xlsx('F:/Data/sales_sample.xlsx', sheet='orders')GROUP BY customer_id
路 ),
路 labeled AS (SELECT
路     o.*,CASE WHEN date_trunc('month', o.order_date) = date_trunc('month', f.first_dt)THEN '新客'ELSE '老客'END AS cust_tag
路   FROM read_xlsx('F:/Data/sales_sample.xlsx', sheet='orders') o
路   JOIN first_order f USING (customer_id))SELECT
路   cust_tag,COUNT(*)             AS orders,COUNT(DISTINCT customer_id) AS buyers,SUM(amount)          AS revenue,ROUND(AVG(amount),2) AS aov
路 FROM labeled
路 GROUP BY cust_tag
路 ORDER BY revenue DESC;
┌─────────────────────────────────────┐
│┌───────────────────────────────────┐│
││    Query Profiling Information    ││
│└───────────────────────────────────┘│
└─────────────────────────────────────┘
EXPLAIN ANALYZE  WITH first_order AS (   SELECT     customer_id,     MIN(order_date) AS first_dt   FROM read_xlsx('F:/Data/sales_sample.xlsx', sheet='orders')   GROUP BY customer_id ), labeled AS (   SELECT     o.*,     CASE WHEN date_trunc('month', o.order_date) = date_trunc('month', f.first_dt)          THEN '新客'          ELSE '老客'     END AS cust_tag   FROM read_xlsx('F:/Data/sales_sample.xlsx', sheet='orders') o   JOIN first_order f USING (customer_id) ) SELECT   cust_tag,   COUNT(*)             AS orders,   COUNT(DISTINCT customer_id) AS buyers,   SUM(amount)          AS revenue,   ROUND(AVG(amount),2) AS aov FROM labeled GROUP BY cust_tag ORDER BY revenue DESC;
┌────────────────────────────────────────────────┐
│┌──────────────────────────────────────────────┐│
││              Total Time: 0.160s              ││
│└──────────────────────────────────────────────┘│
└────────────────────────────────────────────────┘
┌───────────────────────────┐
│           QUERY           │
└─────────────┬─────────────┘
┌─────────────┴─────────────┐
│      EXPLAIN_ANALYZE      │
│    ────────────────────   │
│           0 rows          │
│          (0.00s)          │
└─────────────┬─────────────┘
┌─────────────┴─────────────┐
│         PROJECTION        │
│    ────────────────────   │
│__internal_decompress_strin│
│           g(#0)           │#1            │#2            │#3            │#4            │
│                           │
│           2 rows          │
│          (0.00s)          │
└─────────────┬─────────────┘
┌─────────────┴─────────────┐
│          ORDER_BY         │
│    ────────────────────   │
│  sum(labeled.amount) DESC │
│                           │
│           2 rows          │
│          (0.00s)          │
└─────────────┬─────────────┘
┌─────────────┴─────────────┐
│         PROJECTION        │
│    ────────────────────   │
│__internal_compress_string_│
│        ubigint(#0)        │#1            │#2            │#3            │#4            │
│                           │
│           2 rows          │
│          (0.00s)          │
└─────────────┬─────────────┘
┌─────────────┴─────────────┐
│         PROJECTION        │
│    ────────────────────   │
│          cust_tag         │
│           orders          │
│           buyers          │
│          revenue          │
│            aov            │
│                           │
│           2 rows          │
│          (0.00s)          │
└─────────────┬─────────────┘
┌─────────────┴─────────────┐
│         PROJECTION        │
│    ────────────────────   │
│__internal_decompress_strin│
│           g(#0)           │#1            │#2            │#3            │#4            │
│                           │
│           2 rows          │
│          (0.00s)          │
└─────────────┬─────────────┘
┌─────────────┴─────────────┐
│       HASH_GROUP_BY       │
│    ────────────────────   │
│         Groups: #0        │
│                           │
│        Aggregates:        │
│        count_star()       │
│     count(DISTINCT #1)    │sum(#2)          │avg(#3)          │
│                           │
│           2 rows          │
│          (0.01s)          │
└─────────────┬─────────────┘
┌─────────────┴─────────────┐
│         PROJECTION        │
│    ────────────────────   │
│          cust_tag         │
│        customer_id        │
│           amount          │
│           amount          │
│                           │
│        10,005 rows        │
│          (0.00s)          │
└─────────────┬─────────────┘
┌─────────────┴─────────────┐
│         PROJECTION        │
│    ────────────────────   │
│             #0            │#1            │
│__internal_compress_string_│
│        ubigint(#2)        │
│                           │
│        10,005 rows        │
│          (0.00s)          │
└─────────────┬─────────────┘
┌─────────────┴─────────────┐
│         PROJECTION        │
│    ────────────────────   │
│        customer_id        │
│           amount          │
│          cust_tag         │
│                           │
│        10,005 rows        │
│          (0.00s)          │
└─────────────┬─────────────┘
┌─────────────┴─────────────┐
│         HASH_JOIN         │
│    ────────────────────   │
│      Join Type: INNER     │
│                           │
│        Conditions:        ├──────────────┐
│ customer_id = customer_id │              │
│                           │              │
│        10,005 rows        │              │
│          (0.01s)          │              │
└─────────────┬─────────────┘              │
┌─────────────┴─────────────┐┌─────────────┴─────────────┐
│         PROJECTION        ││       HASH_GROUP_BY       │
│    ────────────────────   ││    ────────────────────   │
│             #2            ││         Groups: #0        │#0            ││    Aggregates: min(#1)    │#1            ││                           │#3            ││                           │#4            ││                           │#5            ││                           │#6            ││                           │#7            ││                           │#8            ││                           │#9            ││                           │#10            ││                           │#11            ││                           │
│                           ││                           │
│        10,005 rows        ││          500 rows         │
│          (0.00s)          ││          (0.01s)          │
└─────────────┬─────────────┘└─────────────┬─────────────┘
┌─────────────┴─────────────┐┌─────────────┴─────────────┐
│         TABLE_SCAN        ││         PROJECTION        │
│    ────────────────────   ││    ────────────────────   │
│    Function: READ_XLSX    ││        customer_id        │
│                           ││         order_date        │
│                           ││                           │
│        10,005 rows        ││        10,005 rows        │
│          (0.08s)          ││          (0.00s)          │
└───────────────────────────┘└─────────────┬─────────────┘┌─────────────┴─────────────┐│         PROJECTION        ││    ────────────────────   ││             #2            │#1            ││                           ││        10,005 rows        ││          (0.00s)          │└─────────────┬─────────────┘┌─────────────┴─────────────┐│         TABLE_SCAN        ││    ────────────────────   ││    Function: READ_XLSX    ││                           ││        10,005 rows        ││          (0.05s)          │└───────────────────────────┘

4.6. 统计对比结果

4.6.1. 对比结论(同一批数据,结果一致)

  • 直接读取 Excel(read_xlsx)与读取已落库表(orders)在数值结果上完全一致(KPI、分组汇总等)。

  • 性能差异显著:落库后查询明显更快(~14×–29×),主要开销来自 READ_XLSX 的解析与转换。

4.6.2. 性能对比(你贴的 EXPLAIN ANALYZE)

场景SQL 对象Total Time加速倍数(落库/Excel)
基础 KPIread_xlsx('…', sheet='orders')0.0569 s
orders(落库表)0.0026 s≈ 21.9×
按地区汇总read_xlsx('…', sheet='orders')0.0899 s
orders(落库表)0.0031 s≈ 29.0×
新客 vs 老客纯落库表版 CTE0.0117 s
全程 read_xlsx0.1600 s≈ 13.7×(落库更快)

注:倍数=(Excel耗时 ÷ 落库耗时);你的执行日志中 TABLE_SCAN Function: READ_XLSX 约耗时 0.04–0.08 s,是主要差异来源。

4.6.3. 结果一致性(摘录)

  • KPI 两种方式数值一致:

    • total_orders=10005

    • total_revenue=94,118,663.73

    • avg_order_value≈9407.16

    • total_qty=35,252

    • paid_txn_cnt=10005

    • buyers=500

  • 按地区汇总两种方式排序、金额完全一致(西南、华中、东北…)。

4.6.4. 为什么落库更快?

  • read_xlsx 每次查询都要 解析 XLSX(ZIP+XML)→ 类型推断 → 转换成列批;无法充分复用缓存。

  • 落库表/本地 .duckdb

    • 数据以 列式、压缩、字典编码 持久化,扫描和聚合开销极小;

    • DuckDB 可复用 buffer cache,算子更少、数据就绪。

4.6.5. 最佳实践建议
  1. 一次性落库或转 Parquet,后续所有分析用表/Parquet:

    -- 落库(你已完成)
    CREATE OR REPLACE TABLE orders AS
    SELECT * FROM read_xlsx('F:/Data/sales_sample.xlsx', sheet='orders');-- 可选:转 Parquet(便于共享与分层存储)
    COPY (SELECT * FROM orders)
    TO 'F:/Data/orders.parquet' (FORMAT PARQUET);
    
  2. 频繁分析/联表/时间序列 → 用落库表或 Parquet;偶尔一次性查看 → 可以 read_xlsx 快速扫。

  3. 需要更高吞吐或共享 → 湖格式(Parquet)+ DuckDB 外表;还可叠加分区/分桶。

4.7. 持久化存储

4.7.1. 内存模式切换为文件模式

D ATTACH 'F:/Data/sales_demo.duckdb' AS dst;
D PRAGMA database_list;
┌───────┬─────────┬───────────────────────────┐
│  seq  │  name   │           file            │
│ int64 │ varcharvarchar          │
├───────┼─────────┼───────────────────────────┤
│   592 │ memory  │ NULL                      │
│  2071 │ dst     │ F:/Data/sales_demo.duckdb │
└───────┴─────────┴───────────────────────────┘
D CREATE OR REPLACE TABLE dst.orders AS SELECT * FROM main.orders;
D CREATE OR REPLACE TABLE dst.customers AS SELECT * FROM main.customers;
D SHOW TABLES FROM dst;
┌───────────┐
│   name    │
│  varchar  │
├───────────┤
│ customers │
│ orders    │
└───────────┘
D SELECT COUNT(*) FROM dst.orders;
┌──────────────┐
│ count_star() │
│    int64     │
├──────────────┤
│    10005     │
└──────────────┘

4.7.2. 打开duckdb

C:\Users\caimingyang>duckdb "F:/Data/sales_demo.duckdb"
DuckDB v1.4.1 (Andium) b390a7c376
Enter ".help" for usage hints.
D SHOW TABLES FROM dst;
Catalog Error:
SHOW TABLES FROM: No catalog + schema named ".dst" found.
D SHOW TABLES;
┌───────────┐
│   name    │
│  varchar  │
├───────────┤
│ customers │
│ orders    │
└───────────┘
D SHOW TABLES;
┌───────────┐
│   name    │
│  varchar  │
├───────────┤
│ customers │
│ orders    │
└───────────┘
D

4.8. ETL数据处理环节

4.8.1. 抽取(E:Extract)

(你已经用 read_xlsx 读入,以下仅列备选)

-- Excel
INSTALL 'excel'; LOAD 'excel';
SELECT * FROM read_xlsx('F:/Data/sales_sample.xlsx', sheet='orders');

4.8.2. 清洗/转换(T:Transform)

4.8.2.1 典型“数据健康”修复
-- 2.1.1 去重(示例:以 order_id 最新记录为准)
CREATE OR REPLACE TABLE stg_orders AS
WITH ranked AS (SELECT o.*,ROW_NUMBER() OVER (PARTITION BY order_id ORDER BY order_date DESC) AS rnFROM read_xlsx('F:/Data/sales_sample.xlsx', sheet='orders') o
)
SELECT * FROM ranked WHERE rn = 1;-- 2.1.2 处理异常 & 缺失:负数/0数量、折扣空值、支付方式空
CREATE OR REPLACE TABLE stg_orders_clean AS
SELECTorder_id,order_date::TIMESTAMP       AS order_date,customer_id,region, channel, category, product,unit_price,CASE WHEN quantity < 0 THEN 0 ELSE quantity END AS quantity,        -- 负数→0(可改“退货单”策略)COALESCE(discount, 0)       AS discount,-- 重新计算金额,避免原始 amount 异常ROUND(unit_price * CASE WHEN quantity < 0 THEN 0 ELSE quantity END * (1 - COALESCE(discount,0)), 2) AS amount,COALESCE(payment_method, '(缺失)') AS payment_method
FROM stg_orders;
4.8.2.2 维表同步(customers)
CREATE OR REPLACE TABLE stg_customers AS
SELECT * FROM read_xlsx('F:/Data/sales_sample.xlsx', sheet='customers');
4.8.2.3 维度派生/口径统一(示例)
-- 增加年月字段、VIP分组
CREATE OR REPLACE TABLE fct_orders AS
SELECT*,date_trunc('month', order_date) AS month,CASEWHEN amount >= 20000 THEN '高额订单'WHEN amount >=  5000 THEN '中额订单'ELSE '普通订单'END AS order_bucket
FROM stg_orders_clean;CREATE OR REPLACE TABLE dim_customers AS
SELECT*,CASE vip_levelWHEN '白金' THEN 'VIP4'WHEN '金卡' THEN 'VIP3'WHEN '银卡' THEN 'VIP2'ELSE 'VIP1'END AS vip_tier
FROM stg_customers;

4.8.3. 落库(L:Load)

(把清洗后的数据固化为 DuckDB 本地表,之后查询更快)

-- 一般我们使用一个库文件(例如 F:/Data/sales_demo.duckdb)启动 DuckDB 后执行:
CREATE SCHEMA IF NOT EXISTS etl;CREATE OR REPLACE TABLE etl.orders     AS SELECT * FROM fct_orders;
CREATE OR REPLACE TABLE etl.customers  AS SELECT * FROM dim_customers;-- 索引(加速过滤/关联)
CREATE INDEX IF NOT EXISTS idx_orders_cust  ON etl.orders(customer_id);
CREATE INDEX IF NOT EXISTS idx_orders_date  ON etl.orders(order_date);
CREATE INDEX IF NOT EXISTS idx_cust_id      ON etl.customers(customer_id);

目录化建议:stg_* 为“过渡(中间层)”,etl.* 为清洗后的成品层。


4.8.4. 导出(多种方式)

4.8.4.1 导出为 Excel
COPY (SELECT * FROM etl.orders
)
TO 'F:/Data/exports/orders.xlsx'
WITH (FORMAT XLSX, SHEET 'orders');

4.9. 视图

DuckDB 支持 视图(VIEW)临时视图(TEMP VIEW)

  • VIEW:保存 SQL 定义的逻辑对象,不存数据;查询时实时计算。

  • TEMP VIEW:会话级视图,断开连接即消失。

  • 物化视图(Materialized View):DuckDB 当前不提供官方 MV 语法(可用“表 + 定期刷新”替代)。

4.9.1 创建视图(示例:KPI 汇总)

D CREATE OR REPLACE VIEW rpt_kpi ASSELECTCOUNT(*)                         AS total_orders,SUM(amount)                      AS total_revenue,AVG(amount)                      AS avg_order_value,COUNT(DISTINCT customer_id)      AS buyers
路 FROM orders;
D select * from rpt_kpi
路 ;
┌──────────────┬───────────────────┬───────────────────┬────────┐
│ total_orders │   total_revenue   │  avg_order_value  │ buyers │
│    int64     │      doubledouble       │ int64  │
├──────────────┼───────────────────┼───────────────────┼────────┤
│    1000594118663.729999579407.162791604154500   │
└──────────────┴───────────────────┴───────────────────┴────────┘
DC:\Users\caimingyang>duckdb "F:/Data/sales_demo.duckdb"
DuckDB v1.4.1 (Andium) b390a7c376
Enter ".help" for usage hints.
D select * from rpt_kpi;
┌──────────────┬───────────────────┬───────────────────┬────────┐
│ total_orders │   total_revenue   │  avg_order_value  │ buyers │
│    int64     │      doubledouble       │ int64  │
├──────────────┼───────────────────┼───────────────────┼────────┤
│    1000594118663.729999579407.162791604154500   │
└──────────────┴───────────────────┴───────────────────┴────────┘

4.9.2. 临时视图(会话内复用中间结果)

CREATE TEMP VIEW v_first_order AS
SELECT customer_id, MIN(order_date) AS first_dt
FROM orders GROUP BY customer_id;-- 使用
SELECT o.customer_id, o.order_id
FROM etl.orders o JOIN v_first_order f USING (customer_id)
WHERE date_trunc('month', o.order_date) = date_trunc('month', f.first_dt);

4.9.3. “物化视图”的替代

-- 以表形式固化 + 定时刷新(脚本/调度器)
CREATE OR REPLACE TABLE mv_monthly_revenue AS
SELECT date_trunc('month', order_date) AS month, SUM(amount) AS revenue
FROM orders
GROUP BY 1;-- “刷新”:先删再建,或 MERGE 增量(按当月/最近N月重算)
DELETE FROM mv_monthly_revenue WHERE month >= date_trunc('month', now()) - INTERVAL '3 months';
INSERT INTO mv_monthly_revenue
SELECT date_trunc('month', order_date), SUM(amount)
FROM orders
WHERE order_date >= date_trunc('month', now()) - INTERVAL '3 months'
GROUP BY 1;
http://www.dtcms.com/a/606660.html

相关文章:

  • 【愚公系列】《MCP协议与AI Agent开发》010-MCP协议标准与规范体系(协议消息结构设计)
  • 3、日常脚本:文件去重(删除重复文件)
  • 物流公司网站方案wordpress搭建系统
  • 个人做负面网站犯法不ui设计行业的现状和发展前景
  • 亚马逊部分退款计划:卖家降本增效新策略
  • 外包公司企业网站学习做网站难吗
  • 分布式环境下的一致性与幂等性
  • 【OpenCV + VS】 使用 OpenCV 实现实时人脸检测
  • 聊城手机网站建设电话达内网站开发视频教程
  • MySQL JOIN 机制与多表查询优化:驱动表选择、连接算法与执行计划解析
  • AI代码开发宝库系列:特征工程
  • WordPress全站广告巩义市建设局网站
  • 信誉好的顺德网站建设如何用百度平台营销
  • Apache Cloudberry 孵化报告(202508-202510)
  • 【2025 JAVA面试题】 常见几个具体问题
  • dedecms大气金融企业网站模板八年级信息所用软件做网站
  • C语言编译器手机| 如何选择适合的C语言编译器应用
  • Java 并发踩坑:高并发库存扣减丢失更新,从悲观锁到分布式锁的终极方案
  • 杭州建设网站职称人才工作专题wordpress 插件手机
  • lancedb create_scalar_index 创建索引
  • Python 网络编程
  • Java后端常用技术选型 |(四)微服务篇
  • Vue3 + Vite项目=》babel转义兼容低版本实现+vite 分包处理方案
  • 【GIS入门】GeoTIFF栅格地理数据格式介绍和基础概念详解
  • 网站开发与设计模板百度seo网站排名
  • 校园网站建设总结flash网站系统
  • openlayer省市县json
  • 计算机视觉11-相机模型与多视几何
  • 网站开发公司 经营范围eclipse做网站表格
  • 建立网站 域名 服务器7一12岁手工简单又实用