用 DuckDB 做电商日报:3 个 SQL 查询搞定传统 BI 工具一周的活

0 阅读7分钟

用 DuckDB 做电商日报:3 个 SQL 查询搞定传统 BI 工具一周的活

每天做电商数据报表?别再用 Tableau 和 Excel 手动拉数据了。本文将带你用 DuckDB 的 3 个核心查询,自动化完成电商日报的全套分析——销售总览、品类深度分析、城市热力图、复购率统计,全部一条 SQL 搞定。

你是否厌倦了每天花 2 小时手动整理电商数据?想要像资深数据工程师一样,仅用几条 SQL 就生成完整的销售日报?本文将带你深入探索 DuckDB 在电商数据分析中的强大能力!从实时销售总览到品类深度分析,从城市热力图到复购率统计,每个知识点都配有实战代码示例。无论你是数据分析师、电商运营还是后端工程师,这些技巧都将大幅提升你的数据分析效率!

你可能有过这样的经历:每天早晨打开电脑,首要任务就是打开 Excel,手动从数据库导出昨天的销售数据,再用透视表做分类汇总,再发结果给老板。光是准备数据就花了一个小时,分析只用了十分钟。而 DuckDB 的做法完全不同:你只需要在现有的数据分析管道里加几条 SQL,日报就自动生成了。没有额外的服务器,没有额外的运维成本,数据就在你的数据库里,查出来直接就能用。

这篇文章的目标很明确:让你在同一个地方完成所有电商数据分析任务。从实时销售总览到品类深度分析,从城市热力图到复购率统计,全部用 SQL 搞定。

一、项目架构:3 个文件搞定整套系统

传统的电商数据报表系统需要搭建 BI 工具、配置数据管道、编写复杂的 ETL 脚本。而 DuckDB 的做法完全不同——它只需要三个文件:

# 1. schema.py — 定义数据表结构
import duckdb

def create_schema(conn):
    # 创建电商数据表结构
    conn.execute("""
        CREATE TABLE IF NOT EXISTS orders (
            order_id BIGINT,
            customer_id BIGINT,
            product_id BIGINT,
            quantity INTEGER,
            price DECIMAL(10, 2),
            order_date DATE,
            city VARCHAR,
            category VARCHAR
        )
    """)
# 2. queries.py — 核心查询逻辑
import duckdb

def get_daily_sales_summary(conn):
    # 实时销售总览查询
    return conn.execute("""
        SELECT 
            DATE(order_date) as sale_date,
            COUNT(*) as total_orders,
            SUM(price * quantity) as total_revenue,
            AVG(price * quantity) as avg_order_value
        FROM orders
        GROUP BY DATE(order_date)
        ORDER BY sale_date DESC
    """).fetchdf()
# 3. main.py — 主程序入口
import duckdb
from schema import create_schema
from queries import get_daily_sales_summary

# 创建数据库连接
conn = duckdb.connect('ecommerce.db')
create_schema(conn)

# 执行查询并输出结果
df = get_daily_sales_summary(conn)
print(df.to_string(index=False))

这三个文件构成了完整的电商日报系统。不需要搭建 BI 工具,不需要配置数据管道,只需要一个 DuckDB 数据库连接和几条 SQL 查询。

二、核心查询 1:实时销售总览与传统工具对比

电商日报的首要步骤是获取实时销售总览。传统方案通常需要编写复杂的 SQL 查询,然后手动整理数据。而 DuckDB 只需要一条查询语句:

-- 实时销售总览查询
SELECT 
    DATE(order_date) as sale_date,
    COUNT(*) as total_orders,
    SUM(price * quantity) as total_revenue,
    AVG(price * quantity) as avg_order_value,
    COUNT(DISTINCT customer_id) as unique_customers
FROM orders
WHERE order_date >= CURRENT_DATE - INTERVAL '7 days'
GROUP BY DATE(order_date)
ORDER BY sale_date DESC;

这个查询返回过去 7 天的销售数据,包括订单总数、总销售额、平均订单价值和独立客户数。与传统工具相比,DuckDB 的优势在于:

  1. 无需部署服务器:DuckDB 是嵌入式数据库,直接在 Python 进程中运行
  2. 查询速度极快:列式存储 + SIMD 优化,比传统关系型数据库快 10 倍以上
  3. 代码简洁:一条 SQL 搞定,无需编写复杂的 ETL 脚本

三、核心查询 2:品类深度分析

电商运营需要了解各个品类的销售表现。传统方案需要编写多条查询语句,然后在 Excel 中手动汇总。而 DuckDB 只需要一条查询:

-- 品类深度分析查询
SELECT 
    category,
    COUNT(*) as product_count,
    SUM(price * quantity) as category_revenue,
    SUM(price * quantity) * 100.0 / (SELECT SUM(price * quantity) FROM orders) as revenue_percentage,
    AVG(price * quantity) as avg_order_value
FROM orders
WHERE order_date >= CURRENT_DATE - INTERVAL '30 days'
GROUP BY category
ORDER BY category_revenue DESC;

这个查询返回各个品类的销售数据,包括商品数量、品类销售额、销售占比和平均订单价值。与传统工具相比,DuckDB 的优势在于:

  1. 子查询支持:直接在同一查询中计算销售占比,无需编写额外的聚合逻辑
  2. 实时计算:数据量在百万级时仍能保持毫秒级响应
  3. 易于扩展:只需要修改 WHERE 条件就可以切换时间范围

四、核心查询 3:城市热力图

城市级别的销售分析对于电商运营非常重要。传统方案需要导入地理信息系统或使用专门的 BI 工具。而 DuckDB 只需要一条查询:

-- 城市级别销售分析查询
SELECT 
    city,
    COUNT(*) as city_orders,
    SUM(price * quantity) as city_revenue,
    COUNT(DISTINCT customer_id) as city_customers,
    PERCENT_RANK() OVER (ORDER BY SUM(price * quantity)) as revenue_rank
FROM orders
WHERE order_date >= CURRENT_DATE - INTERVAL '7 days'
GROUP BY city
ORDER BY city_revenue DESC;

这个查询返回各个城市的销售数据,包括订单数、销售额、客户数和销售排名。与传统工具相比,DuckDB 的优势在于:

  1. 窗口函数支持:使用 PERCENT_RANK() 直接计算销售排名,无需编写额外的排名逻辑
  2. 内存高效:城市数据量在万级时仍能保持毫秒级响应
  3. 易于可视化:查询结果可以直接用于生成热力图

五、核心查询 4:复购率分析

复购率是电商运营的核心指标之一。传统方案需要编写复杂的 SQL 查询来计算复购率。而 DuckDB 只需要一条查询:

-- 复购率分析查询
WITH customer_orders AS (
    SELECT 
        customer_id,
        COUNT(*) as order_count,
        MIN(order_date) as first_order_date
    FROM orders
    WHERE order_date >= CURRENT_DATE - INTERVAL '90 days'
    GROUP BY customer_id
)
SELECT 
    COUNT(*) as total_customers,
    SUM(CASE WHEN order_count > 1 THEN 1 ELSE 0 END) as repeat_customers,
    SUM(CASE WHEN order_count > 1 THEN 1 ELSE 0 END) * 100.0 / COUNT(*) as repeat_rate
FROM customer_orders;

这个查询返回过去 90 天的复购率数据,包括总客户数、复购客户数和复购率。与传统工具相比,DuckDB 的优势在于:

  1. CTE 支持:使用 WITH 语句构建复杂的分析逻辑,代码更易读
  2. 条件聚合:使用 SUM(CASE WHEN ...) 直接计算复购率,无需编写额外的计算逻辑
  3. 易于维护:查询逻辑清晰,易于理解和维护

六、性能优化建议

对于大规模电商数据,DuckDB 的性能优化建议如下:

  1. 使用 Parquet 格式存储数据:Parquet 是列式存储格式,查询速度比 CSV 快 10 倍以上
  2. 创建索引:对于频繁查询的字段,创建索引可以显著提升查询速度
  3. 使用分区表:对于时间序列数据,使用分区表可以提高查询效率
# 使用 Parquet 格式存储数据
conn.execute("""
    COPY orders TO 'orders.parquet' (FORMAT PARQUET);
""")

# 从 Parquet 文件读取数据
df = conn.execute("SELECT * FROM 'orders.parquet'").fetchdf()

七、生态集成

DuckDB 与 Python 生态的完美集成,使得电商数据分析变得更加简单:

import duckdb
import pandas as pd

# 创建 DuckDB 连接
conn = duckdb.connect('ecommerce.db')

# 执行查询并获取 Pandas DataFrame
df = conn.execute("SELECT * FROM orders").fetchdf()

# 使用 Pandas 进行进一步分析
daily_sales = df.groupby('order_date').agg({
    'price': 'sum',
    'quantity': 'sum'
}).reset_index()

# 使用 Matplotlib 生成可视化图表
import matplotlib.pyplot as plt

plt.figure(figsize=(12, 6))
plt.plot(daily_sales['order_date'], daily_sales['price'], label='Daily Sales')
plt.title('Daily Sales Trend')
plt.xlabel('Date')
plt.ylabel('Sales')
plt.legend()
plt.show()

总结

通过这篇文章,我们展示了 DuckDB 在电商数据分析中的强大能力。从实时销售总览到品类深度分析,从城市热力图到复购率统计,DuckDB 都用简洁的 SQL 查询完成了传统 BI 工具需要一周才能完成的工作。

DuckDB 的优势在于:

  1. 无需部署服务器:嵌入式数据库,直接在 Python 进程中运行
  2. 查询速度极快:列式存储 + SIMD 优化,比传统关系型数据库快 10 倍以上
  3. 代码简洁:一条 SQL 搞定,无需编写复杂的 ETL 脚本
  4. 易于扩展:只需要修改查询条件就可以切换分析维度

如果你还在用 Excel 或 Tableau 做电商数据分析,不妨试试 DuckDB。你一定会被它的速度和简洁性所震撼!

参考资料