SQL Server 日期范围按每月一行拆分

给定一个日期,按月每行拆分。

复制代码
CREATE TABLE #temp(from_date DATE,to_date DATE);
INSERT INTO #temp (from_date,to_date) VALUES ( '2013-10-25','2013-12-05');
SELECT * FROM #temp;

SELECT  CASE n.number WHEN 0 THEN d.from_date
          ELSE DATEADD(MONTH, n.number,DATEADD(DAY, 1 - DAY(from_date), from_date))
        END [start_date],
        CASE n.number WHEN DATEDIFF(MONTH, d.from_date, d.to_date) THEN to_date
          ELSE DATEADD(DAY, -1,DATEADD(MONTH, 1,DATEADD(MONTH, n.number, DATEADD(DAY, 1 - DAY(from_date),from_date))))
        END [end_date]
FROM    master.dbo.spt_values n
        INNER JOIN #temp AS d ON d.to_date >= DATEADD(MONTH, n.number - 1,d.from_date)
WHERE   type = 'p'
复制代码

 

原始数据集:

拆分结果集:

 modfiy 2021/12/21 来自园友 是小凯i 的指正,在此感谢:),日期范围是当月或者结束日期 日数字 大于 开始日期 日数字的时候会出现多出一个月的结果,修正后如下:

方法一

复制代码
CREATE TABLE #temp(from_date DATE,to_date DATE);
INSERT INTO #temp (from_date,to_date) VALUES ( '2013-10-25','2013-11-20');
SELECT * FROM #temp;

SELECT  CASE n.number WHEN 0 THEN d.from_date
          ELSE DATEADD(MONTH, n.number,DATEADD(DAY, 1 - DAY(from_date), from_date))
        END [start_date],
        CASE n.number WHEN DATEDIFF(MONTH, d.from_date, d.to_date) THEN to_date
          ELSE DATEADD(DAY, -1,DATEADD(MONTH, 1,DATEADD(MONTH, n.number, DATEADD(DAY, 1 - DAY(from_date),from_date))))
        END [end_date]
FROM    master.dbo.spt_values n
        INNER JOIN #temp AS d ON CONVERT(CHAR(6),d.to_date,112) >= CONVERT(CHAR(6),DATEADD(MONTH, n.number,d.from_date),112) AND d.to_date>d.from_date
WHERE   type = 'p'  
复制代码

 

结果:

方法二

复制代码
CREATE TABLE #temp(from_date DATE,to_date DATE);
INSERT INTO #temp (from_date,to_date) VALUES ( '2013-10-25','2013-11-20');
SELECT * FROM #temp;

WITH CTE as 
    (
    SELECT from_date,to_date,from_date as [start_date], 
             CASE WHEN DATEADD(DAY,-DAY(DATEADD(MONTH,1, d.from_date)),DATEADD(MONTH,1, d.from_date))< To_date 
                       THEN DATEADD(DAY,-DAY(DATEADD(MONTH,1, d.from_date)),DATEADD(MONTH,1, d.from_date))
                       ELSE To_Date END as [end_date]
      FROM #temp d
      UNION ALL 
      SELECT from_date,To_date,DATEADD(DAY,1,[end_date]), 
             CASE WHEN DATEADD(DAY,-1,DATEADD(MONTH,1,DATEADD(DAY,1,[end_date])))< To_date 
                       THEN DATEADD(DAY,-1,DATEADD(MONTH,1,DATEADD(DAY,1,[end_date])))
                       ELSE To_Date END FROM CTE WHERE [end_date] < To_Date
      )
 SELECT [start_date],[end_date] FROM CTE ORDER BY from_date,[end_date];
复制代码

 

结果同上

 

 

已知一个数,得知那些行的合计后等于这个数

复制代码
CREATE TABLE #t(ID VARCHAR(1),数据 INT)
INSERT INTO #t
select 'a',10 union all
select 'b',90 union all
select 'c',100 union all
select 'd',180 union ALL
select 'e',15 union ALL
select 'f',5;
with ps as
(
select *,path=cast(id as varchar(8000)),path1=cast(数据 as varchar(8000)),total=数据 from #t
union all
select b.id,b.数据,a.path+','+b.id,path1+','+ltrim(b.数据), a.total+b.数据
from ps a join #t b on a.id<b.id and a.total<200
)

select path,path1,total from ps where total=200
复制代码

 

posted @   VicLW  阅读(1313)  评论(0编辑  收藏  举报
编辑推荐:
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律
点击右上角即可分享
微信分享提示