基于本文回答
0
评论

给定每日销售额,编写 SQL 计算 2025 年每天的 GMV,并计算截止到当天(年初至今)的累计销售额

面试题:2025年每日销售额及年初至今(YTD)累计销售额计算

1. 题目背景与要求

在电商和零售行业中,实时监控每日 GMV(商品交易总额)以及当年的累计销售额(Year-to-Date, 简称 YTD)是运营和财务部门最核心的数据需求之一。

请编写 SQL,基于给定的每日销售明细表,计算 2025 年每天的 GMV,以及截止到当天(2025年初至当天)的累计销售额


2. 示例数据

输入表:sales_records(每日销售明细表)

sales_date (销售日期) sales_amount (销售金额)
2024-12-31 5000.00
2025-01-01 10000.00
2025-01-02 15000.00
2025-01-03 12000.00
2025-01-04 20000.00
2025-01-05 18000.00
2025-02-01 25000.00

期望输出结果:

sales_date daily_gmv ytd_gmv (2025年初至今累计)
2025-01-01 10000.00 10000.00
2025-01-02 15000.00 25000.00
2025-01-03 12000.00 37000.00
2025-01-04 20000.00 57000.00
2025-01-05 18000.00 75000.00
2025-02-01 25000.00 100000.00

注:2024-12-31 的数据不应参与 2025 年的累计计算。


3. SQL 解答

sql
SELECT 
    sales_date,
    sales_amount AS daily_gmv,
    SUM(sales_amount) OVER (
        ORDER BY sales_date 
        ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
    ) AS ytd_gmv
FROM 
    sales_records
WHERE 
    sales_date >= '2025-01-01' 
    AND sales_date <= '2025-12-31'
ORDER BY 
    sales_date;

4. 深度解析与面试应对指南

在面试中,这道题表面上考察的是窗口函数,但面试官更看重候选人对执行顺序性能优化边界条件的理解。

核心考点一:窗口函数 SUM() OVER () 的使用
  • 计算累计值:累计计算(Running Total / Cumulative Sum)的标准解法是使用窗口函数。
  • 语法拆解
    • ORDER BY sales_date:指定按照日期先后顺序进行累加。
    • ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW:明确定义窗口范围为从第一行(起点)到当前行
    • 面试官可能会问:如果不写 ROWS BETWEEN... 会怎么样?
      • 解答:如果不写,默认的窗口范围是 RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW。在有重复日期的极端情况下,RANGE 会把相同日期的值加和后再计算,而 ROWS 则是逐行计算。明确写出 ROWS 执行效率更高,且逻辑更严谨。
核心考点二:过滤条件(WHERE)与窗口函数的执行顺序

这是本题最容易出错的地方。SQL 的执行顺序是:FROM -> WHERE -> SELECT (及窗口函数) -> ORDER BY

  • 如果我们先在 WHERE 中过滤了 sales_date >= '2025-01-01',那么进入窗口函数的数据只包含 2025 年及以后的数据
  • 因此,UNBOUNDED PRECEDING(起点)自然变成了 2025-01-01,完美实现了“年初至今(YTD)”的累计,而不会把 2024 年的 5000.00 元算进来。
  • 避坑指南:千万不要使用子查询先算全局累计再用 WHERE 过滤日期,那样会导致 2025 年的数据包含了 2024 年的底数,不符合 “YTD(年初至今)” 的定义。
核心考点三:性能优化(Index 索引)

如果面试官追问:“如果这个表有几千万行数据,如何优化这个查询?”

  • 索引优化:确保在 sales_date 列上有索引。
  • 范围查询优势:在 WHERE 子句中,我们使用了 sales_date >= '2025-01-01' AND sales_date <= '2025-12-31',这种范围写法(Range Query)可以直接利用索引快速定位数据。
  • 反面教材:避免写成 WHERE YEAR(sales_date) = 2025。因为对索引列使用函数(如 YEAR())会导致索引失效,触发全表扫描。
右滑查看面试常问