如何查询PLAN_DATA表中PID=12的连续周数据?
解决连续周查询问题的方案
嘿,我看你当前的SQL只能把符合条件的周、月分组列出来,但没法识别哪些周是连续的对吧?别担心,咱们用CTE(公共表表达式)和窗口函数就能搞定这个需求,下面是具体的实现思路和代码:
问题分析
你的核心需求是找出username='peter'、2018年、pid=12的连续周序列,而当前的查询只是单独列出每个符合条件的周,缺少连续性的判断逻辑。
完整SQL实现
-- 先设置周起始日(可选,若需要周一为一周第一天则打开此行) -- SET DATEFIRST 1; WITH UniqueWeeks AS ( -- 第一步:去重,获取所有符合条件的唯一周数(避免同一周多条数据干扰) SELECT DISTINCT username, DATEPART(w, workdate) AS week_num, DATEPART(m, workdate) AS month_num, YEAR(workdate) AS year_num FROM plan_data WHERE username = 'peter' AND YEAR(workdate) = 2018 AND pid = 12 ), WeekGroups AS ( -- 第二步:计算当前周与前一周的差值,标记连续性 SELECT username, week_num, month_num, year_num, -- 用LAG窗口函数获取上一个周的编号,计算差值 week_num - LAG(week_num) OVER (PARTITION BY username, year_num ORDER BY week_num) AS diff_from_prev FROM UniqueWeeks ), GroupedWeeks AS ( -- 第三步:给每个连续周序列分配唯一组ID SELECT username, week_num, month_num, year_num, -- 累计求和:当差值≠1(或为第一个周)时,新建一个组 SUM(CASE WHEN diff_from_prev <> 1 OR diff_from_prev IS NULL THEN 1 ELSE 0 END) OVER (PARTITION BY username, year_num ORDER BY week_num ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS group_id FROM WeekGroups ) -- 第四步:统计每个连续周序列的信息 SELECT username, year_num AS year, MIN(week_num) AS start_week, MAX(week_num) AS end_week, -- 列出组内所有连续周(SQL Server 2017+支持STRING_AGG) STRING_AGG(week_num, ', ') AS consecutive_weeks_list FROM GroupedWeeks GROUP BY username, year_num, group_id HAVING COUNT(*) >= 2 -- 只保留至少连续2周的序列(若需要包含单周可去掉此行) ORDER BY year, start_week;
关键步骤说明
- UniqueWeeks:先对周数去重,因为同一周可能有多条
pid=12的记录,去重后能避免后续判断出错。 - WeekGroups:使用
LAG()函数获取当前周的上一个周编号,计算两者的差值——如果差值为1,说明这两周是连续的。 - GroupedWeeks:通过累计求和生成组ID,每当遇到不连续的周(差值≠1)或者是第一个周时,就新建一个组,这样同一连续序列的周会被分到同一个组里。
- 最后一步:按组统计连续周的起始、结束周数,还可以用
STRING_AGG()列出所有连续的周编号,方便查看。
注意事项
DATEPART(w, workdate)的周数计算受SQL Server的DATEFIRST设置影响,默认是周日为一周第一天,如果需要以周一为起始日,可以在查询前加上SET DATEFIRST 1;。- 如果你需要单独列出每一个连续的周(而不是分组成序列),可以去掉最后一步的分组,直接查询
GroupedWeeks中diff_from_prev=1的记录即可。
内容的提问来源于stack exchange,提问作者ManiMuthuPandi
相关产品推荐
相关产品推荐

