基于另一列的一个值生成新列的多行

x33g5p2x  于 2022-10-22  发布在  其他
关注(0)|答案(2)|浏览(152)

我有一张如下表:
|ID |日期|
| ------------ | ------------ |
| 1 | 2022-01-01 |
| 2 | 2022-03-21 |
我想根据日期添加一个新列,它应该如下所示
|ID |日期|新列|
| ------------ | ------------ | ------------ |
| 1 | 2022-01-01 | 2022-02-01 |
| 1 | 2022-01-01 | 2022-03-01 |
| 1 | 2022-01-01 | 2022-04-01 |
| 1 | 2022-01-01 | 2022-05-01 |
| 2 | 2022-03-21 | 2022-04-21 |
| 2 | 2022-03-21 | 2022-05-21 |
假设有一个*@EndDate=2022-05-31*(这是它应该停止的地方)
我很难弄清楚如何在SSMS中做到这一点。非常感谢您的任何见解!谢谢:)

nvbavucw

nvbavucw1#

在下面的解决方案中,我们将string_split与replicate结合使用以生成新记录。

select    ID
         ,Date
         ,dateadd(month, row_number() over(partition by ID  order by (select null)), Date) as NewCol
from     (
         select   *
         from     t
         outer apply string_split(replicate(',',datediff(month, Date, '2022-05-31')-1),',')
         ) t
ID日期新列
12022-01-012022-02-01
12022-01-012022-03-01
12022-01-012022-04-01
12022-01-012022-05-01
22022-03-212022-04-21
22022-03-212022-05-21

Fiddle
对于Azure和SQL Server 2022中的SQL,我们有一个基于[ordinal][4]的更干净的解决方案。
“Azure SQL数据库、Azure SQL托管示例和Azure Synapse Analytics(仅限无服务器SQL池)当前支持enable_ordinal参数和ordinal输出列。从SQL Server 2022(16.x)预览版开始,SQL Server中提供了参数和输出列。”

select    ID
         ,Date
         ,dateadd(month, ordinal, Date) as NewCol
from     (
         select   *
         from     t
         outer apply string_split(replicate(',',datediff(month, Date, '2022-05-31')-1),',',1)
         ) t
f4t66c6m

f4t66c6m2#

有很多方法可以将一行“分解”为一组,我认为最简单的方法是递归CTE:

DECLARE @endpoint date = '20220531';

DECLARE @prev date = DATEADD(MONTH, -1, @endpoint);

WITH x AS
(
  SELECT ID, date, NewCol = DATEADD(MONTH, 1, date) FROM #d
  UNION ALL
  SELECT ID, date, DATEADD(MONTH, 1, NewCol) FROM x
    WHERE NewCol < @prev
)
SELECT * FROM x
  ORDER BY ID, NewCol;

this fiddle中的工作示例。
请记住,如果您有超过100个月的时间,则需要添加OPTION (MAXRECURSION)(或考虑使用不同的解决方案)。

相关问题