热线电话:13121318867

登录
首页大数据时代SQL应用实例:从电商业务场景看经典查询写法
SQL应用实例:从电商业务场景看经典查询写法
2026-10-20
收藏

一、为什么要通过实例学SQL

SQL是数据从业者最基础也最高频的工具。很多人学过SELECT、WHERE、GROUP BY,但一到真实业务里就写不出有效查询——问题不在语法,而在于不知道"业务问题该翻译成哪种查询结构"。

本文围绕电商数据分析中最常见的几类真实问题,逐一给出可直接套用的SQL实例。每个案例都包含业务场景、问题描述、完整SQL写法和结果解读。掌握这些实例背后的思维方式,遇到类似问题就能快速套用。

所有示例基于经典的三张业务表:users(用户表)、orders(订单表)、order_items(订单明细表)。

二、经典场景一:每个分组内取Top N

2.1 问题描述

这是SQL面试和业务分析中最高频的一类问题:查询每个部门工资最高的员工。换成电商场景就是:查询每个品类下销售额最高的商品。

2.2 解法:窗口函数 ROW_NUMBER

-- 每个品类下销售额排名前3的商品
SELECT category, product_name, total_amount
FROM (
    SELECT 
        category,
        product_name,
        SUM(amount) AS total_amount,
        ROW_NUMBER() OVER (
            PARTITION BY category 
            ORDER BY SUM(amount) DESC
        ) AS rn
    FROM order_items
    GROUP BY category, product_name
) t
WHERE rn <= 3;

2.3 三种排名函数的区别

窗口函数里有三个长得像但用法不同的排名函数,业务中经常搞混:

函数 特点 适用场景
ROW_NUMBER() 即使并列也强制编号1,2,3 需要严格取前N条,如取前3名
RANK() 并列占名次,下一名跳号(1,1,3) 比赛排名、允许并列
DENSE_RANK() 并列不跳号(1,1,2) 等级划分、分档统计

三、经典场景二:连续登录N天的用户

3.1 问题描述

用户留存分析中最经典的问题:找出连续登录3天及以上的用户。这个问题考察的是"日期差法"这种经典技巧。

3.2 解法:日期差法(行号减日期)

WITH login_dates AS (
    -- 先去重,每个用户每天只算一次登录
    SELECT DISTINCT user_id, login_date
    FROM user_logins
),
grouped AS (
    SELECT 
        user_id,
        login_date,
        -- 关键技巧:日期减去行号,连续日期会得到相同的值
        DATE_SUB(
            login_date, 
            INTERVAL ROW_NUMBER() OVER (
                PARTITION BY user_id 
                ORDER BY login_date
            ) DAY
        ) AS date_group
    FROM login_dates
)
SELECT user_id, COUNT(*) AS consecutive_days
FROM grouped
GROUP BY user_id, date_group
HAVING COUNT(*) >= 3;

3.3 原理解释

这个方法的精髓是:把连续的日期序列减去一个递增的行号,连续日期会"坍缩"成同一个分组值。比如日期序列 7-1,7-2,7-3 减去行号 1,2,3,结果都是 6-30。不连续的日期就会落入不同分组,再按分组计数就能找出连续段。

四、经典场景三:漏斗转化分析

4.1 问题描述

电商分析的核心问题之一:用户从"浏览商品"到"加入购物车"到"提交订单"到"支付成功",每一步的转化率是多少?

4.2 解法:条件聚合

SELECT 
    COUNT(DISTINCT CASE WHEN event = 'view' THEN user_id END) AS step_view,
    COUNT(DISTINCT CASE WHEN event = 'cart' THEN user_id END) AS step_cart,
    COUNT(DISTINCT CASE WHEN event = 'order' THEN user_id END) AS step_order,
    COUNT(DISTINCT CASE WHEN event = 'pay' THEN user_id END) AS step_pay
FROM user_events
WHERE event_date BETWEEN '2024-01-01' AND '2024-01-31';

4.3 结果解读

查出来四个数之后,转化率就是:

  • 加购率 = step_cart ÷ step_view
  • 下单率 = step_order ÷ step_cart
  • 支付率 = step_pay ÷ step_order

条件聚合(CASE WHEN + COUNT DISTINCT)是做漏斗、做行列转换、做"在一行里看多列指标"的核心技巧,比多次JOIN子查询高效得多。

五、经典场景四:同比与环比计算

5.1 问题描述

每个月的销售额出来后,要算本月比上月增长多少(环比)、本月比去年同月增长多少(同比)。

5.2 解法:自连接或LAG函数

WITH monthly_sales AS (
    SELECT 
        DATE_FORMAT(order_date, '%Y-%m') AS month,
        SUM(amount) AS sales
    FROM orders
    GROUP BY DATE_FORMAT(order_date, '%Y-%m')
)
SELECT 
    month,
    sales,
    -- 环比:和上一个月比
    ROUND(
        (sales - LAG(sales) OVER (ORDER BY month)) 
        / LAG(sales) OVER (ORDER BY month) * 100, 2
    ) AS mom_growth_pct,
    -- 同比:和去年同月比(隔12行)
    ROUND(
        (sales - LAG(sales, 12) OVER (ORDER BY month)) 
        / LAG(sales, 12) OVER (ORDER BY month) * 100, 2
    ) AS yoy_growth_pct
FROM monthly_sales
ORDER BY month;

5.3 要点

  • 环比用 LAG(列, 1),同比用 LAG(列, 12)(按月数据)。
  • 一定要处理除零:分母为0时同比会报错,用 NULLIF() 包一下。
  • 同环比分析是运营月报、季报的固定栏目,这套写法可以直接复用。

六、经典场景五:去重计数与占比计算

6.1 问题描述

经常遇到这种问题:统计每个品类的销售额占全店总销售额的比例。

6.2 解法:窗口函数 SUM 做全局汇总

SELECT 
    category,
    SUM(amount) AS category_sales,
    ROUND(
        SUM(amount) / SUM(SUM(amount)) OVER () * 100, 
        2
    ) AS sales_ratio_pct
FROM order_items
GROUP BY category;

6.3 要点

注意 SUM(SUM(amount)) OVER () 这种"嵌套聚合 + 窗口函数"的写法:内层 SUM(amount) 是按品类聚合,外层 SUM(...) OVER () 是在聚合结果上再求全局总和。这种写法比"子查询查总数再相除"简洁得多,是写占比、排名、累计占比的标准模式。

七、经典场景六:行列转换(行转列)

7.1 问题描述

原始数据是长表(每行一个事件),要转成宽表(每个用户一行,列出各行为次数):

原始表:

user_id event_type cnt
1001 view 10
1001 cart 3
1002 view 8

要变成:

user_id view_cnt cart_cnt order_cnt
1001 10 3 1

7.2 解法:CASE WHEN 聚合

SELECT 
    user_id,
    SUM(CASE WHEN event_type = 'view' THEN cnt ELSE 0 END) AS view_cnt,
    SUM(CASE WHEN event_type = 'cart' THEN cnt ELSE 0 END) AS cart_cnt,
    SUM(CASE WHEN event_type = 'order' THEN cnt ELSE 0 END) AS order_cnt
FROM user_events_summary
GROUP BY user_id;

行列转换是报表宽表、数据脱敏、特征工程里天天用的操作,记住"CASE WHEN + 聚合"这个万能模板即可。

八、SQL思维:从业务问题到查询结构

做完这些实例,可以提炼出几条通用的SQL思维方法:

第一,先分层,再写SQL。 复杂查询不要一次性写到底,用CTE(WITH子句)把问题拆成几步:先清洗、再聚合、最后计算。每一层只做一件事,可读性和可调试性都大幅提升。

第二,善用窗口函数替代自连接。 排名、连续问题、环比同比、占比,这些场景用窗口函数写通常比自连接、多层子查询简洁一个数量级。窗口函数是现代SQL最值得掌握的武器。

第三,聚合方向想清楚。 写GROUP BY之前先问自己:我要的是"每个分组一条结果",还是"每条原始行都带聚合值"?前者用GROUP BY,后者用窗口函数。

第四,性能敏感时先看执行计划。 大表JOIN、全表扫描、函数包裹索引列导致索引失效,这些问题靠看不出来,要 EXPLAIN 一下执行计划。

九、总结

SQL不是背语法,而是训练一种"结构化思维"——把一个模糊的业务问题,拆成明确的表、明确的字段、明确的聚合逻辑。本文列出的六个场景——分组TopN、连续登录、漏斗转化、同环比、占比、行列转换——覆盖了电商数据分析中80%以上的日常查询。把这些实例理解透、能默写,再遇到新问题时,往往只需要在这些模板上换字段、换条件即可。

真正的SQL高手不是会写最复杂的嵌套语句,而是能用最简洁的查询解决业务问题。从实例中提炼模式,再用模式去解新题,这就是SQL应用能力的进阶路径。

推荐学习书籍 《CDA一级教材》适合CDA一级考生备考,也适合业务及数据分析岗位的从业者提升自我。完整电子版已上线CDA网校,累计已有10万+在读~ !

免费加入阅读:https://edu.cda.cn/goods/show/3151?targetId=5147&preview=0

数据分析师资讯
更多

OK
客服在线
立即咨询
客服在线
立即咨询