CASE表达式中DATEADD函数异常,如何实现PowerBI动态月度统计?
动态筛选上月/上上月全月数据的SQL实现
核心问题分析
原查询无结果或数据范围错误的根源是日期逻辑判断偏差:
DATEADD(MONTH, -1, GETDATE())返回的是「上个月的当前日期」(比如今日是2023-06-15,返回2023-05-15),而非上月全月范围,所以精确匹配会无结果- 后续的
>= DATEADD(MONTH, -1, GETDATE()) AND < DATEADD(MONTH, 0, GETDATE())实际筛选的是「上个月当前日到本月当前日」的区间,不是自然月全月,导致包含当月数据
正确的动态日期范围写法
要精准获取自然月全月数据,需计算目标月份的第一天和下一个月的第一天(左闭右开区间):
上月全月
-- 上月第一天 DATEFROMPARTS(YEAR(GETDATE()), MONTH(GETDATE())-1, 1) -- 本月第一天(作为上月范围的结束边界,不包含) DATEFROMPARTS(YEAR(GETDATE()), MONTH(GETDATE()), 1)
上上月全月
-- 上上月第一天 DATEFROMPARTS(YEAR(GETDATE()), MONTH(GETDATE())-2, 1) -- 上月第一天(作为上上月范围的结束边界,不包含) DATEFROMPARTS(YEAR(GETDATE()), MONTH(GETDATE())-1, 1)
优化后的完整查询
建议先在JOIN阶段过滤目标日期范围(提升查询效率),再统计各类操作次数:
统计上月数据版本
WITH UserCounts AS ( SELECT U.dbuser_id, U.user_name, SUM(CASE WHEN R.primary_user_id = U.dbuser_id THEN 1 ELSE 0 END) AS primary_count, SUM(CASE WHEN R.secondary_user_id = U.dbuser_id THEN 1 ELSE 0 END) AS secondary_count, SUM(CASE WHEN R.dblentry_user_id = U.dbuser_id THEN 1 ELSE 0 END) AS dblentry_count FROM valid_users U LEFT JOIN requests R ON U.dbuser_id IN (R.primary_user_id, R.secondary_user_id, R.dblentry_user_id) -- 筛选上月全月数据 AND R.entry_date >= DATEFROMPARTS(YEAR(GETDATE()), MONTH(GETDATE())-1, 1) AND R.entry_date < DATEFROMPARTS(YEAR(GETDATE()), MONTH(GETDATE()), 1) GROUP BY U.dbuser_id, U.user_name ) SELECT dbuser_id, user_name, primary_count, secondary_count, dblentry_count, primary_count + secondary_count + dblentry_count AS total_count FROM UserCounts WHERE primary_count > 0 OR secondary_count > 0 OR dblentry_count > 0
统计上上月数据版本
仅需替换JOIN中的日期过滤条件:
-- 替换为上上月范围 AND R.entry_date >= DATEFROMPARTS(YEAR(GETDATE()), MONTH(GETDATE())-2, 1) AND R.entry_date < DATEFROMPARTS(YEAR(GETDATE()), MONTH(GETDATE())-1, 1)
特殊场景处理
如果entry_date(创建日期)、secondary_dt(录入日期)、dblentry_dt(复核日期)可能分属不同月份,需要分别对每个操作的日期做范围过滤,调整CASE WHEN逻辑:
SUM(CASE WHEN R.primary_user_id = U.dbuser_id AND R.entry_date >= DATEFROMPARTS(YEAR(GETDATE()), MONTH(GETDATE())-1, 1) AND R.entry_date < DATEFROMPARTS(YEAR(GETDATE()), MONTH(GETDATE()), 1) THEN 1 ELSE 0 END) AS primary_count, SUM(CASE WHEN R.secondary_user_id = U.dbuser_id AND R.secondary_dt >= DATEFROMPARTS(YEAR(GETDATE()), MONTH(GETDATE())-1, 1) AND R.secondary_dt < DATEFROMPARTS(YEAR(GETDATE()), MONTH(GETDATE()), 1) THEN 1 ELSE 0 END) AS secondary_count, SUM(CASE WHEN R.dblentry_user_id = U.dbuser_id AND R.dblentry_dt >= DATEFROMPARTS(YEAR(GETDATE()), MONTH(GETDATE())-1, 1) AND R.dblentry_dt < DATEFROMPARTS(YEAR(GETDATE()), MONTH(GETDATE()), 1) THEN 1 ELSE 0 END) AS dblentry_count
内容的提问来源于stack exchange,提问作者BrettFK
相关产品推荐
相关产品推荐

