编写SQL查询计算含前日销售额的累计值遇问题求助
正确SQL方案:计算包含前日销售额的累计总额
问题根源分析
你写的SQL存在两个核心错误:
- 布尔表达式误用:
t1.salesum=t1.salesum+t2.salesum是判断等式是否成立的逻辑,而非计算求和,因此返回布尔值f(false)。 - 自连接逻辑错误:用
t1.saledate=t2.saledate连接,本质是每条记录和自身匹配,完全无法实现“获取前日销售额”的需求。
从你的预期结果来看,需求是每个销售日的销售额,加上前一个最近销售日的销售额(若为首个销售日则仅取当日金额)。
推荐方案:窗口函数(主流数据库通用)
利用LAG()窗口函数直接获取前一个销售日的销售额,代码简洁高效:
SELECT saledate, salesum + COALESCE(LAG(salesum) OVER(ORDER BY saledate), 0) AS salesum FROM sales ORDER BY saledate;
关键说明:
LAG(salesum) OVER(ORDER BY saledate):按销售日期排序,自动获取当前行的前一行销售额;第一行无前置行时返回NULL。COALESCE(..., 0):将NULL替换为0,保证首个销售日的结果为当日销售额。
执行该语句即可得到你需要的预期结果。
兼容方案:自连接(适配旧版数据库)
若你的数据库不支持窗口函数,可通过子查询+自连接实现:
SELECT t1.saledate, t1.salesum + COALESCE(t2.salesum, 0) AS salesum FROM sales t1 LEFT JOIN sales t2 ON t2.saledate = ( SELECT MAX(saledate) FROM sales WHERE saledate < t1.saledate ) ORDER BY t1.saledate;
关键说明:
- 子查询
SELECT MAX(saledate) FROM sales WHERE saledate < t1.saledate:定位当前日期之前的最后一个销售日。 LEFT JOIN确保即使无前置销售日(如2022-01-01),当前行仍会被保留,此时t2.salesum为NULL。COALESCE将NULL转为0,避免求和结果出现NULL。
附:原始问题信息
源表(sales)
| saledate(销售日期) | salesum(销售金额) |
|---|---|
| 2022-01-01 | 100 |
| 2022-01-02 | 150 |
| 2022-01-03 | 200 |
| 2022-01-05 | 100 |
预期结果
| saledate(销售日期) | salesum(累计销售金额) |
|---|---|
| 2022-01-01 | 100 |
| 2022-01-02 | 250 |
| 2022-01-03 | 350 |
| 2022-01-05 | 300 |
错误查询语句
SELECT t1.saledate, t1.salesum=t1.salesum+t2.salesum FROM sales t1 INNER JOIN ( SELECT saledate, salesum FROM sales ) t2 ON t1.saledate=t2.saledate;
错误执行结果
| saledate(销售日期) | salesum |
|---|---|
| 2022-01-01 | f |
| 2022-01-02 | f |
| 2022-01-03 | f |
| 2022-01-05 | f |
内容的提问来源于stack exchange,提问作者altchist
相关产品推荐
相关产品推荐

