Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/27.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
SQL在给定开始日期和年数的情况下,获取每年的开始日期和结束日期行_Sql_Sql Server - Fatal编程技术网

SQL在给定开始日期和年数的情况下,获取每年的开始日期和结束日期行

SQL在给定开始日期和年数的情况下,获取每年的开始日期和结束日期行,sql,sql-server,Sql,Sql Server,我在SQL表中有以下数据: +------------------------------------+ | ID YEARS START_DATE | +------------------------------------+ | ----------- ----------- ---------- | | 1 5 2020-12-01 | | 2 8 2020-12-01 | +-

我在SQL表中有以下数据:

+------------------------------------+
| ID          YEARS       START_DATE |
+------------------------------------+
| ----------- ----------- ---------- |
| 1           5           2020-12-01 |
| 2           8           2020-12-01 |
+------------------------------------+
尝试创建一个SQL,它将扩展上述数据,并根据上表中的年份和开始日期,为我提供每年的开始和结束日期。样本输出如下:

+-----------------------------------------------+
|  ID          YEAR        DATE_START DATE_END  |
+-----------------------------------------------+
| ----------- ----------- ---------- ---------- |
| 1           1           2020-12-01 2021-11-30 |
| 1           2           2021-12-01 2022-11-30 |
| 1           3           2022-12-01 2023-11-30 |
| 1           4           2023-12-01 2024-11-30 |
| 1           5           2024-12-01 2025-11-30 |
| 2           1           2020-12-01 2021-11-30 |
| 2           2           2021-12-01 2022-11-30 |
| 2           3           2022-12-01 2023-11-30 |
| 2           4           2023-12-01 2024-11-30 |
| 2           5           2024-12-01 2025-11-30 |
| 2           6           2025-12-01 2026-11-30 |
| 2           7           2026-12-01 2027-11-30 |
| 2           8           2027-12-01 2028-11-30 |
+-----------------------------------------------+

您可以使用递归CTE:

with cte as (
      select id, 1 as year, start_date,
             dateadd(day, -1, dateadd(year, 1, start_date)) as end_date,
             years as num_years
      from t
      union all
      select id, year + 1, dateadd(year, 1, start_date),
             dateadd(day, -1, dateadd(year, 1, start_date)) as end_date,
             num_years             
      from cte
      where year < num_years
     )
select id, year, start_date, end_date
from cte;

是一个dbfiddle。

您可以使用递归CTE:

with cte as (
      select id, 1 as year, start_date,
             dateadd(day, -1, dateadd(year, 1, start_date)) as end_date,
             years as num_years
      from t
      union all
      select id, year + 1, dateadd(year, 1, start_date),
             dateadd(day, -1, dateadd(year, 1, start_date)) as end_date,
             num_years             
      from cte
      where year < num_years
     )
select id, year, start_date, end_date
from cte;

是一个dbfiddle。

我会使用内联计数,因为它们比递归CTE解决方案快得多。假设您的值多年来一直较低:

以你的桌子为例 挑选* 根据转换日期'20201201'的值1,5, 2,8,转换日期,'20201201'视频,年份,起始日期 选择ID, V.I+1作为[年度], DATEADDYEAR,V.I,YT.起始日期作为起始日期, DATEADDDAY,-1,DATEADDYEAR,V.I+1,YT.StartDate作为结束日期 从你的桌子上 累计年数大于一年的合并价值0,1,2,3,4,5,6,7,8,9,10VI; 如果你有超过10年的时间,你可以使用创建一个理货表,或者在CTE中创建一个大的内联表格。这将从以下方面开始:

以N作为 选择N 来自valuesnall,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULLNN, 算作 通过选择NULL-1作为I选择订单上的行号-如果不想从0开始,请删除-1 从N N1、N N2到100行,为更多行添加更多N ...
当然,我怀疑你是否有1000年的数据。

我会使用内联计数,因为它们比递归CTE解决方案快得多。假设您的值多年来一直较低:

以你的桌子为例 挑选* 根据转换日期'20201201'的值1,5, 2,8,转换日期,'20201201'视频,年份,起始日期 选择ID, V.I+1作为[年度], DATEADDYEAR,V.I,YT.起始日期作为起始日期, DATEADDDAY,-1,DATEADDYEAR,V.I+1,YT.StartDate作为结束日期 从你的桌子上 累计年数大于一年的合并价值0,1,2,3,4,5,6,7,8,9,10VI; 如果你有超过10年的时间,你可以使用创建一个理货表,或者在CTE中创建一个大的内联表格。这将从以下方面开始:

以N作为 选择N 来自valuesnall,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULLNN, 算作 通过选择NULL-1作为I选择订单上的行号-如果不想从0开始,请删除-1 从N N1、N N2到100行,为更多行添加更多N ...
当然,我怀疑您是否有1000年的数据。

在查询中,您可以使用以下内容:

DATEADD(YEAR, 1, DATE_START) - 1
要将其添加到表中,只需创建额外的列,并将其设置为上述值,例如

UPDATE MyTable
SET DATE_END = DATEADD(YEAR, 1, DATE_START) - 1

在查询中,可以使用以下选项:

DATEADD(YEAR, 1, DATE_START) - 1
要将其添加到表中,只需创建额外的列,并将其设置为上述值,例如

UPDATE MyTable
SET DATE_END = DATEADD(YEAR, 1, DATE_START) - 1

如果您使用的是sql server,则可以尝试将运算符交叉应用于master.dbo.spt_值表,以获取数字列表并生成日期:

 select ID,T.number+1 as YEAR, 
 --generate date_start using T.number
 dateadd(year,T.number,START_DATE)date_start,
 --generate end_date: adding 1 year to start date  
 dateadd(dd,-1,dateadd(year,1,dateadd(year,T.number,START_DATE)))date_end 
 from Table
 cross apply
 master.dbo.spt_values T
 where T.type='P' and T.number<YEARS

如果您使用的是sql server,则可以尝试将运算符交叉应用于master.dbo.spt_值表,以获取数字列表并生成日期:

 select ID,T.number+1 as YEAR, 
 --generate date_start using T.number
 dateadd(year,T.number,START_DATE)date_start,
 --generate end_date: adding 1 year to start date  
 dateadd(dd,-1,dateadd(year,1,dateadd(year,T.number,START_DATE)))date_end 
 from Table
 cross apply
 master.dbo.spt_values T
 where T.type='P' and T.number<YEARS

小心你的假设——以及假设是如何流入建议的。开始日期可以不是一个月的第一天吗?在你说“不”之前,是不是有一个约束来阻止它?如果没有,那么你就有一个非常隐秘的错误等待被发现。小心你的假设——以及假设是如何流入建议的。开始日期可以不是一个月的第一天吗?在你说“不”之前,是不是有一个约束来阻止它?如果没有,那么你就有一个非常隐蔽的错误等待被发现。