Featured image of post DuckDB 数据清洗与盈利分析实战:从混乱 CSV 到精准利润报表

DuckDB 数据清洗与盈利分析实战:从混乱 CSV 到精准利润报表

用 DuckDB 的 read_csv_auto、REGEXP_REPLACE、CAST 和窗口函数,一站式完成多平台脏数据的标准化清洗与盈利分析。附 ABC 分级模型和变现建议。

数据标准化与盈利分析流程

从混乱 CSV 到精准报表:DuckDB 的一站式解决方案

你是否有过这样的经历?接手一个客户的数据项目,对方甩给你十几个 CSV 和 Excel 文件——有的用中文列名,有的用英文;有的日期格式是 2026-07-01,有的是 01/07/2026,还有的是 July 1, 2026;金额列里混杂着 ¥1,234.56$1,234.561,234.56元 等各种格式。

传统做法是用 Python 写一堆 pandas 清洗脚本,或者手动在 Excel 里替换。但 DuckDB 用一条 SQL 就能搞定这一切。

今天我们要做的,是一个真实存在的副业方向:为多平台电商卖家提供数据清洗与盈利分析服务。一套 DuckDB 脚本可以服务几十个客户,边际成本趋近于零。


一、数据标准化:三个平台的订单,一条 SQL 统一

假设你接到一个多平台电商卖家的数据需求,需要合并拼多多、淘宝、Shopify 三个平台的订单数据。每个平台的导出格式完全不同:

拼多多导出格式:

订单号,商品名称,实付金额,订单状态,下单时间
PDD123456,iPhone 15 壳,¥29.90,已完成,2026-07-01 14:30:00

淘宝导出格式:

order_id,product_title,pay_amount,status,create_time
TB789012,MagSafe 充电器,$49.00,TRADE_SUCCESS,2026-07-01 15:20:00

Shopify 导出格式:

order_number,item_name,total_price,fulfilled_status,created_at
#1001,Case + Charger Bundle,€78.90,fulfilled,2026-07-01T16:00:00Z

第一步:分别读取并标准化每个平台的数据

-- 读取拼多多数据,标准化字段
CREATE OR REPLACE TABLE pdd_raw AS
SELECT
    'pdd' AS platform,
    TRIM(订单号) AS order_id,
    TRIM(商品名称) AS product_name,
    CAST(REGEXP_REPLACE(实付金额, '[¥¥,]', '') AS DOUBLE) AS amount,
    CASE
        WHEN 订单状态 LIKE '%已完成%' THEN 'completed'
        WHEN 订单状态 LIKE '%退款%' THEN 'refunded'
        WHEN 订单状态 LIKE '%取消%' THEN 'cancelled'
        ELSE 'pending'
    END AS status,
    CAST(下单时间 AS TIMESTAMP) AS order_time
FROM read_csv_auto('pinduoduo_orders.csv');

-- 读取淘宝数据,标准化字段
CREATE OR REPLACE TABLE taobao_raw AS
SELECT
    'taobao' AS platform,
    TRIM(order_id) AS order_id,
    TRIM(product_title) AS product_name,
    CAST(REGEXP_REPLACE(pay_amount, '[¥¥$,]', '') AS DOUBLE) AS amount,
    CASE
        WHEN status LIKE '%已完成%' THEN 'completed'
        WHEN status LIKE '%退款%' THEN 'refunded'
        WHEN status LIKE '%取消%' THEN 'cancelled'
        ELSE 'pending'
    END AS status,
    CAST(create_time AS TIMESTAMP) AS order_time
FROM read_csv_auto('taobao_orders.csv');

-- 读取 Shopify 数据,标准化字段
CREATE OR REPLACE TABLE shopify_raw AS
SELECT
    'shopify' AS platform,
    TRIM(order_number) AS order_id,
    TRIM(item_name) AS product_name,
    CAST(REGEXP_REPLACE(total_price, '[€£$,¥¥,]', '') AS DOUBLE) AS amount,
    CASE
        WHEN fulfilled_status IN ('fulfilled', 'shipped') THEN 'completed'
        WHEN fulfilled_status IN ('refunded', 'cancelled') THEN 'refunded'
        ELSE 'pending'
    END AS status,
    CAST(created_at AS TIMESTAMP) AS order_time
FROM read_csv_auto('shopify_orders.csv');

这里的关键技术点:

  • REGEXP_REPLACE:一键清除所有货币符号和千分位逗号,不用写 Python 正则
  • CAST(... AS TIMESTAMP):DuckDB 能自动识别多种时间格式,包括 ISO 8601、美国格式、中文格式
  • CASE WHEN:将各平台不同的状态枚举值映射为标准值
  • read_csv_auto():自动推断列类型,无需预先定义 schema

第二步:合并为统一表

CREATE OR REPLACE TABLE all_orders AS
SELECT * FROM pdd_raw
UNION ALL SELECT * FROM taobao_raw
UNION ALL SELECT * FROM shopify_raw;

现在所有数据都在一张表里了,后续分析只需要查这一张表。


二、核心盈利分析:算清每一笔账

数据干净之后,我们回答卖家最关心的问题:到底赚了多少钱?

-- 多维度盈利分析
WITH platform_summary AS (
    SELECT
        platform,
        COUNT(*) AS total_orders,
        COUNT(*) FILTER (WHERE status = 'completed') AS completed_orders,
        COUNT(*) FILTER (WHERE status = 'refunded') AS refunded_orders,
        ROUND(SUM(amount) FILTER (WHERE status = 'completed'), 2) AS gross_revenue,
        ROUND(SUM(amount) FILTER (WHERE status = 'refunded'), 2) AS refund_amount,
        ROUND(AVG(amount) FILTER (WHERE status = 'completed'), 2) AS avg_order_value,
        ROUND(
            1.0 * COUNT(*) FILTER (WHERE status = 'refunded')
            / NULLIF(COUNT(*), 0) * 100, 2
        ) AS refund_rate_pct
    FROM all_orders
    GROUP BY platform
)
SELECT * FROM platform_summary
ORDER BY gross_revenue DESC;

这个查询的输出告诉卖家:

  • 每个平台的实际营收(扣除退款后)
  • 退货率(直接影响利润的关键指标)
  • 客单价(决定营销策略的基础数据)

进阶:带时间维度的盈利趋势

-- 按周分析各平台营收趋势,加入环比变化
WITH weekly_revenue AS (
    SELECT
        platform,
        DATE_TRUNC('week', order_time) AS trade_week,
        ROUND(SUM(amount) FILTER (WHERE status = 'completed'), 2) AS revenue,
        COUNT(*) FILTER (WHERE status = 'completed') AS orders,
        -- 环比:与上一周的差异
        LAG(ROUND(SUM(amount) FILTER (WHERE status = 'completed'), 2))
            OVER (PARTITION BY platform ORDER BY DATE_TRUNC('week', order_time)) AS prev_week_revenue,
        -- 周环比增长率
        ROUND(
            (SUM(amount) FILTER (WHERE status = 'completed')
            - LAG(SUM(amount) FILTER (WHERE status = 'completed'))
                OVER (PARTITION BY platform ORDER BY DATE_TRUNC('week', order_time)))
            / NULLIF(LAG(SUM(amount) FILTER (WHERE status = 'completed'))
                OVER (PARTITION BY platform ORDER BY DATE_TRUNC('week', order_time)), 0)
            * 100, 2
        ) AS week_over_week_change
    FROM all_orders
    GROUP BY platform, DATE_TRUNC('week', order_time)
)
SELECT * FROM weekly_revenue
ORDER BY platform, trade_week;

这里用到了两个强大的窗口函数:

  • LAG():访问前一行的数据,计算环比变化
  • FILTER (WHERE ...):在聚合中做条件过滤,比传统的 SUM(CASE WHEN ...) 简洁得多

三、ABC 分级:找出现金牛和拖油瓶

知道总收入还不够,卖家还需要知道哪些 SKU 在赚钱,哪些在亏钱。这就是经典的 ABC 分析法。

-- ABC 分析:按销售额给 SKU 分级
WITH sku_stats AS (
    SELECT
        product_name,
        platform,
        COUNT(*) AS order_count,
        ROUND(SUM(amount) FILTER (WHERE status = 'completed'), 2) AS total_revenue,
        ROUND(AVG(amount) FILTER (WHERE status = 'completed'), 2) AS avg_price,
        COUNT(*) FILTER (WHERE status = 'refunded') AS refund_count,
        -- 累计销售额占比(用于 ABC 分级)
        SUM(SUM(amount) FILTER (WHERE status = 'completed'))
            OVER (ORDER BY SUM(amount) FILTER (WHERE status = 'completed') DESC)
            / NULLIF(SUM(SUM(amount) FILTER (WHERE status = 'completed')))
            OVER () AS cumulative_revenue_share
    FROM all_orders
    GROUP BY product_name, platform
)
SELECT
    product_name,
    platform,
    order_count,
    total_revenue,
    avg_price,
    refund_count,
    ROUND(cumulative_revenue_share * 100, 2) AS cum_rev_pct,
    CASE
        WHEN cumulative_revenue_share <= 0.7 THEN 'A级(现金牛)'
        WHEN cumulative_revenue_share <= 0.9 THEN 'B级(稳定款)'
        ELSE 'C级(长尾款)'
    END AS sku_tier,
    -- 退货率预警
    CASE
        WHEN ROUND(
            1.0 * refund_count / NULLIF(order_count, 0) * 100, 2
        ) > 15 THEN '⚠️ 退货率过高'
        ELSE '✅ 正常'
    END AS risk_flag
FROM sku_stats
ORDER BY total_revenue DESC;

这个查询的输出可以直接交给卖家:

  • A 级 SKU:占总销售额 70% 的核心产品,应该加大推广
  • B 级 SKU:占总销售额 70%-90% 的稳定产品,保持现有策略
  • C 级 SKU:长尾产品,考虑是否下架
  • 退货率预警:退货率超过 15% 的产品标红提醒

四、与传统工具的对比

维度ExcelPandasDuckDB
多格式 CSV 合并手动复制粘贴需写 Python 循环一条 SQL 搞定
货币符号清洗VLOOKUP + SUBSTITUTE正则表达式 + 循环REGEXP_REPLACE 一行
时间格式统一分列 + 文本转换多次 pd.to_datetimeCAST AS TIMESTAMP 自动识别
百万行聚合卡死可行但慢毫秒级
部署成本文件共享需要 Python 环境单机可运行
复用性每次都要重做脚本需维护SQL 模板复制即用

五、变现建议:这套技能值多少钱?

个人接单模式

  • 定价:500-2000 元/客户/月
  • 客户来源:闲鱼、淘宝服务市场、跨境电商社群
  • 交付物:一份 DuckDB 脚本 + 每周自动生成的分析报告
  • 边际成本:一套脚本可以服务几十个客户,只需替换数据文件路径

SaaS 化模式

  • 将 DuckDB 嵌入 FastAPI 后端,提供 Web 界面
  • 卖家上传 CSV → 自动分析 → 输出 HTML 报告
  • 定价:99-299 元/月/店铺
  • 参考案例:duckdb-fastapi-analytics-saas 已有完整实现

数据产品模式

  • 制作通用的电商分析模板,在 Gumroad/知识星球出售
  • 定价:199-499 元/份
  • 附带视频教程 + 模板脚本 + 客服答疑

核心优势:会 SQL 的人不懂电商业务,懂电商的人不会 SQL。你能同时解决这两个群体的痛点,这就是你的护城河。


六、总结

今天我们从零开始,演示了如何用 DuckDB 完成一个完整的电商数据清洗与盈利分析流程:

  1. 数据标准化:用 REGEXP_REPLACECASTCASE WHEN 清洗多平台脏数据
  2. 统一合并UNION ALL 将异构数据合为一张标准表
  3. 盈利分析:用 FILTER + 窗口函数计算各平台营收和趋势
  4. ABC 分级:用 SUM() OVER (ORDER BY ...) 做累计占比分析
  5. 风险预警:自动标记高退货率 SKU

整个过程只需要纯 SQL,不需要写一行 Python。这就是 DuckDB 的核心竞争力——把数据处理和数据分析统一在同一个引擎里

本文的完整版已发布在 duckdblab.org,包含更详细的步骤和更多案例。

📺 Watch video tutorials → Olap Studio YouTube

Subscribe for more DuckDB & AI automation tutorials

使用 Hugo 构建
主题 StackJimmy 设计

⚠️ 本站为独立社区项目,与 DuckDB 基金会及 DuckDB 官方项目无任何从属、背书或赞助关系。

"DuckDB" 是 DuckDB 基金会的注册商标,本站仅以事实描述方式使用该名称。

本站内容仅供教育与社区推广用途,不构成任何商业服务。