SUM累计窗口统计的两种实现方法示例

SUM累计窗口函数的使用案例

需求说明

请查询出借款时间在近七天内的借款用户中,每天借款时已还清借款3次以上的用户数。查询宇段应包含: 借款日期,借款用户数。

 解决方法

WITH CTE AS(
SELECT 1 id,2343432 AS uid,'2020-09-01' load_date,'20d' load_periods,1 load_status,1 replay_status, NULL payoff_date  UNION ALL
SELECT 2 id,12312133 AS uid,'2020-09-02' load_date,'30d' load_periods,2 load_status,2 replay_status,'2020-10-02' payoff_date UNION ALL
SELECT 3 id,2343431 AS uid,'2020-09-03' load_date,'15d' load_periods,2 load_status,2 replay_status, '2020-09-18' payoff_date  UNION ALL
SELECT 4 id,2343431 AS uid,'2020-09-04' load_date,'20d' load_periods,2 load_status,1 replay_status, NULL payoff_date  UNION ALL
SELECT 5 id,2343432 AS uid,'2022-09-01' load_date,'20d' load_periods,2 load_status,2 replay_status, '2022-09-19' payoff_date  UNION ALL
SELECT 6 id,12312133 AS uid,'2022-09-02' load_date,'18d' load_periods,2 load_status,2 replay_status,'2022-09-17' payoff_date UNION ALL
SELECT 7 id,2343431 AS uid,'2022-09-14' load_date,'15d' load_periods,2 load_status,2 replay_status, '2022-09-29' payoff_date  UNION ALL
SELECT 8 id,2343431 AS uid,'2022-09-04' load_date,'20d' load_periods,2 load_status,1 replay_status, NULL payoff_date UNION ALL
SELECT 9 id,2343432 AS uid,'2022-11-06' load_date,'20d' load_periods,2 load_status,2 replay_status, '2022-11-26' payoff_date  UNION ALL
SELECT 10 id,12312133 AS uid,'2022-11-02' load_date,'14d' load_periods,2 load_status,2 replay_status,'2022-11-13' payoff_date UNION ALL
SELECT 11 id,2343431 AS uid,'2022-11-05' load_date,'20d' load_periods,2 load_status,2 replay_status, '2022-11-25' payoff_date  UNION ALL
SELECT 12 id,2343431 AS uid,'2023-11-04' load_date,'20d' load_periods,2 load_status,1 replay_status, NULL payoff_date UNION ALL
SELECT 13 id,9876 AS uid,'2022-10-06' load_date,'20d' load_periods,2 load_status,2 replay_status, '2022-10-21' payoff_date UNION ALL
SELECT 14 id,9876 AS uid,'2023-10-04' load_date,'14d' load_periods,2 load_status,2 replay_status, '2023-10-14' payoff_date UNION ALL
SELECT 15 id,2343432 AS uid,'2023-01-31' load_date,'15d' load_periods,2 load_status,1 replay_status, NULL payoff_date  UNION ALL
SELECT 16 id,12312133 AS uid,'2023-01-31' load_date,'14d' load_periods,2 load_status,1 replay_status, NULL payoff_date UNION ALL
SELECT 17 id,2343431 AS uid,'2023-02-01' load_date,'20d' load_periods,2 load_status,1 replay_status, NULL payoff_date   UNION ALL
SELECT 18 id,12312133 AS uid,'2023-02-01' load_date,'12d' load_periods,2 load_status,1 replay_status, NULL payoff_date UNION ALL
SELECT 19 id,2343432 AS uid,'2023-02-01' load_date,'15d' load_periods,2 load_status,2 replay_status, '2023-02-02' payoff_date UNION ALL
SELECT 20 id,2343432 AS uid,'2023-02-03' load_date,'15d' load_periods,2 load_status,1 replay_status, NULL payoff_date UNION ALL
SELECT 21 id,9876 AS uid,'2023-02-03' load_date,'15d' load_periods,2 load_status,1 replay_status, NULL payoff_dat
    )

-- #方法1:用窗口函数,注意累加时当前的行不参与SUM
SELECT load_date,COUNT(uid) repaly3timesUser_cnt,date_gap,DATE_FORMAT(now(),'%Y-%m-%d') current FROM
    (
        SELECT DATEDIFF(now(), load_date)  date_gap,
               -- SUM(CASE WHEN replay_status = '2' THEN 1 ELSE NULL END) OVER (PARTITION BY uid ORDER BY load_date rows between unbounded preceding and 1 following) repalyCurr_cnt,
               SUM(CASE WHEN replay_status = '2' THEN 1 ELSE NULL END)
                   OVER (PARTITION BY uid ORDER BY load_date ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING) repalyBeforeCurr_cnt,
               load_date,uid
        FROM CTE
        -- WHERE uid = '2343432' #验证用户
    )A
WHERE date_gap<=7 AND date_gap>=0 AND repalyBeforeCurr_cnt>=3
GROUP BY load_date
-- #方法2:用临时表,先取出近7天用户数据,再跟原表关联统计历史还清贷款数,最终再汇总还了3笔以上的用户数。(注释掉方法1的代码再执行)

,last7day AS (
    SELECT load_date, uid
    FROM CTE
    WHERE DATEDIFF(now(), load_date) <= 7
      AND DATEDIFF(now(), load_date) >= 0
),repalyDetail AS (
    SELECT SUM(CASE WHEN replay_status = '2' THEN 1 ELSE NULL END) repaly_cnt, B.uid, B.load_date
    FROM CTE A
             JOIN last7day B
                  ON A.uid = B.uid AND DATEDIFF(B.load_date, A.load_date) > 0
    GROUP BY B.uid, B.load_date
)
SELECT load_date,COUNT(uid) repaly3timesUser_cnt,DATEDIFF(now(), load_date) date_gap,DATE_FORMAT(now(),'%Y-%m-%d') current
FROM repalyDetail
WHERE repaly_cnt >=3
GROUP BY load_date

03-18
<think>好的,我现在需要回答用户关于在SQL中使用SUM函数进行求和操作的问题。首先,我得仔细理解用户的需求。用户提到了几个引用,特别是关于基础求和、条件求和以及窗口函数的使用。我需要结合这些引用来组织答案,同时遵循系统级指令中的格式要求。 首先,我应该介绍SUM函数的基本用法,比如对单列求和,这时候需要引用引用[1]中的例子。这部分相对简单,但需要确保语法正确,比如在SQL语句中使用SELECT SUM(column) FROM table的结构。 接下来是条件求和,用户提到的SUMIF在SQL中可能需要使用CASE WHEN结合SUM函数,或者使用特定数据库支持的函数如SUM(CASE WHEN condition THEN value ELSE 0 END)。这里要参考引用[2],提到SUMIF在SQL中的实现方式,可能还需要说明不同数据库的差异。 然后是窗口函数的部分,用户提到的滑动求和和累计求和,这部分需要引用引用[3]中的例子。我需要解释OVER()子句的用法,特别是PARTITION BY和ORDER BY的作用,以及如何指定范围,比如ROWS BETWEEN。这部分可能会涉及一些复杂的语法,需要确保示例正确,比如展示一个包含分组和排序的查询。 最后,用户可能需要实际应用的例子,比如统计每个部门的销售总额,或者计算累计销售额。这时候需要给出具体的例子,并说明每个部分的作用。同时,注意事项部分需要提醒用户关于NULL值的处理、性能问题以及不同数据库的兼容性。 在格式方面,需要确保行内数学公式用$...$,但可能在这个问题中用不上数学公式,但如果有类似聚合函数的概念,可能需要用公式表示。独立公式可能也不适用,但如果有需要,比如展示某种计算过程,可以用$$...$$。不过,根据示例,可能更多的是代码块和文字说明。 还需要生成相关问题,可能包括SUM函数的高级用法、与其他聚合函数的区别、性能优化、处理NULL的技巧,以及在不同数据库中的差异。这些问题应该自然相关,帮助用户进一步学习。 现在要检查是否有遗漏的部分,比如是否正确引用了所有相关的引用,特别是引用[3]中的窗口函数部分,是否详细说明了滑动求和和累计求和的例子。还要确保回答结构清晰,分步骤讲解,帮助用户逐步理解。 可能需要注意避免技术术语过多,但用户的问题是技术性的,所以适当的术语是必要的。同时,确保代码示例正确,比如在展示窗口函数时,是否正确使用了OVER(PARTITION BY ... ORDER BY ... ROWS BETWEEN ...)。 总结一下,回答的结构应该是: 1. 基本求和:介绍SUM的基本用法,引用[1] 2. 条件求和:使用CASE WHEN或特定函数,引用[2] 3. 窗口函数:累计和滑动求和,引用[3] 4. 应用实例:具体例子 5. 注意事项:NULL、性能、兼容性 6. 相关问题:生成几个相关问题 需要确保每个部分都有对应的引用标注,比如在基本求和末尾添加[^1],在条件求和部分添加[^2],窗口函数部分添加[^3]。同时,代码块需要用正确的SQL语法,可能包括不同的示例,如基础求和、条件求和、窗口函数的使用。 现在开始组织语言,确保符合中文回答,结构清晰,分点说明,并自然融入引用标识。</think>### SQL中SUM函数的用法详解 #### 1. **基础求和操作** SUM函数用于对数据列的值求和,返回所有值的总和。语法为: ```sql SELECT SUM(column_name) FROM table_name; ``` 例如,统计订单表`orders`中的总销售额: ```sql SELECT SUM(amount) AS total_sales FROM orders; ``` 这会返回`amount`列所有值的总和,并命名为`total_sales`[^1]。 --- #### 2. **条件求和** 若需对满足特定条件的数据求和,可通过`CASE WHEN`或`FILTER`子句实现: - **使用`CASE WHEN`**: ```sql SELECT SUM(CASE WHEN category = '电子产品' THEN amount ELSE 0 END) AS electronic_sales FROM orders; ``` - **使用`FILTER`(部分数据库支持,如PostgreSQL)**: ```sql SELECT SUM(amount) FILTER (WHERE category = '电子产品') AS electronic_sales FROM orders; ``` 这两种方式均可实现“仅对‘电子产品’类别的销售额求和”[^2]。 --- #### 3. **窗口函数:累计与滑动求和** SUM函数结合`OVER()`子句可实现复杂的分组统计: - **累计求和**:统计每个月的累计销售额: ```sql SELECT month, SUM(sales) OVER (ORDER BY month ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS cumulative_sales FROM monthly_sales; ``` - **滑动求和**:计算近3个月的移动平均销售额: ```sql SELECT month, SUM(sales) OVER (ORDER BY month RANGE BETWEEN 2 PRECEDING AND CURRENT ROW) AS moving_avg FROM monthly_sales; ``` `RANGE`指定时间范围,`ROWS`则按行数滑动。 --- #### 4. **实际应用示例** - **按部门统计工资总额**: ```sql SELECT department, SUM(salary) AS total_salary FROM employees GROUP BY department; ``` - **计算季度累计销售额**: ```sql SELECT quarter, SUM(revenue) OVER (PARTITION BY year ORDER BY quarter) AS quarterly_cumulative FROM financial_report; ``` --- #### 5. **注意事项** - **NULL值处理**:SUM函数自动忽略NULL,若需包含可改用`COALESCE(column, 0)`。 - **性能优化**:对大数据表使用窗口函数时,需合理设计索引。 - **数据库兼容性**:`FILTER`子句在MySQL中不支持,需改用`CASE WHEN`。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ShenLiang2025

您的鼓励是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值