You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何不使用UNION按日期范围分组?附SQL Server 2012 T-SQL代码

解决方案:用递归CTE生成周范围,替代循环查询

嘿,我明白你现在的需求——原来的循环会每次输出一周的结果,现在想把这些周的数据整合在一起,不用UNION拼接多次查询,同时按日期范围(每周)来分组处理对吧?

针对SQL Server 2012,推荐用**递归CTE(公共表表达式)**来生成你需要的8个周的日期范围,然后一次性关联所有数据,这样既避免了循环的低效,也不用写一堆UNION。

完整实现代码

DECLARE @START DATE, @END DATE;
-- 假设这里已经给@START和@END赋值,比如SET @START = '2024-01-01', @END = '2024-01-07';

WITH WeeklyRanges AS (
    -- 初始行:第0周(也就是你最初的@START和@END对应的周)
    SELECT 
        0 AS WeekOffset, -- 标记是往前推了几周,0是当前周,7是最老的那周
        @START AS WeekStart,
        @END AS WeekEnd
    UNION ALL
    -- 递归生成往前的7周,直到总共8周(0到7)
    SELECT 
        WeekOffset + 1,
        DATEADD(wk, -1, WeekStart),
        DATEADD(wk, -1, WeekEnd)
    FROM WeeklyRanges
    WHERE WeekOffset < 7
)
-- 关联周范围、预约单和就诊记录
SELECT 
    wr.WeekOffset,
    wr.WeekStart,
    wr.WeekEnd,
    Visits.idPatient,
    Visits.VDay,
    so.SDay
FROM WeeklyRanges wr
-- 先关联所有预约单,再左连接对应周的就诊记录
CROSS JOIN tblScheduledOrder so
LEFT OUTER JOIN (
    SELECT 
        idPatient,
        DATEPART(dw, VDate) - 1 AS VDay,
        VDate
    FROM tblVisits
) Visits 
    ON so.idPatient = Visits.idPatient
    AND Visits.VDate BETWEEN wr.WeekStart AND wr.WeekEnd
-- 如果需要按周分组统计,比如每个周的就诊数,可以加GROUP BY
-- GROUP BY wr.WeekOffset, wr.WeekStart, wr.WeekEnd, Visits.idPatient, Visits.VDay, so.SDay
OPTION (MAXRECURSION 10); -- SQL Server默认递归次数是100,这里只需要8次,所以设置10足够

代码说明

  • 递归CTE生成周范围:
    • 初始部分定义了第0周的起始和结束日期;
    • 递归部分每次把日期往前推1周,直到生成8个周(WeekOffset从0到7)。
  • 关联数据:
    • 用CROSS JOIN先取出所有预约单记录;
    • 左连接就诊记录时,通过Visits.VDate BETWEEN wr.WeekStart AND wr.WeekEnd确保只匹配对应周的就诊数据,同时保留没有就诊记录的预约单(符合你原来LEFT OUTER JOIN的逻辑)。
  • 分组处理:
    • 如果需要按周做聚合统计(比如每个周每个患者的就诊次数),直接在SELECT里加聚合函数(比如COUNT(Visits.idPatient)),然后按wr.WeekOffset、wr.WeekStart等字段分组即可。

这个方法比原来的循环高效得多,因为是单次查询,减少了多次执行SELECT的开销,而且结果集是统一的,方便后续处理。

内容的提问来源于stack exchange,提问作者paulvd

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 07:55:28