之前可能已经提出并回答了这个问题,但是我甚至难以将其作为一个问题(因此标题)来表达。
我有一个数据库表,基本上是
[EventId] INT,
[FirstOccurance_Month] DATETIME,
[LastOccurance_Month] DATETIME
有一些类似的数据:
[EventId] [FirstOccurance_Month] [LastOccurance_Month]
1 2015-11-01 2016-01-01
2 2015-12-01 2016-03-01
3 2016-02-01 2016-02-01
我想要实现的是一个SQL语句,它将EventId作为一列输出,并将其作为第二列发生的所有月份输出。所以对于上面的数据,它看起来像这样:
[EventId] [Month]
1 2015-11-01
1 2015-12-01
1 2016-01-01
2 2015-12-01
2 2016-01-01
2 2016-02-01
2 2016-03-01
3 2016-02-01
我有一种感觉它会涉及CROSS APPLY,所以我要找出实际上是什么......
答案 0 :(得分:3)
您可以使用Tally表执行此任务:
;WITH Tally AS (
SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) - 1 AS i
FROM (VALUES (0), (0), (0), (0), (0)) AS t1(n)
CROSS JOIN (VALUES (0), (0), (0), (0), (0)) AS t2(n)
)
SELECT m.EventId, DATEADD(m, t.i, FirstOccurance_Month) AS [Month]
FROM Tally AS t
INNER JOIN mytable AS m
ON DATEADD(m, t.i, FirstOccurance_Month) <= LastOccurance_Month
ORDER BY m.EventId
上述查询使用的Tally表包含25行。您可以轻松调整它以满足您的实际需求。
答案 1 :(得分:1)
一种方法是使用递归CTE
; with rcte as
(
select EventId, [Month] = FirstOccurance_Month
from yourtable
union all
select t.EventId, [Month] = dateadd(month, 1, r.[Month])
from rcte r
inner join yourtable t on r.EventId = t.EventId
where r.[Month] < t.LastOccurance_Month
)
select *
from rcte
答案 2 :(得分:0)
为了完整起见,这是最终的解决方案。我还在调查接受的答案到底在做什么,它看起来比我的好......
DECLARE @startDate DATETIME = DATEADD(MONTH,-1,(SELECT MIN(DATEADD(MONTH, DATEDIFF(MONTH, 0, [FirstOccurance_Month]), 0)) FROM LogTable))
DECLARE @endDate DATETIME = (SELECT DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()), 0))
SELECT * FROM
(
SELECT DATEADD(MONTH, num, firstdate) AS [DateTime] FROM
(
SELECT a.[num] FROM
(
SELECT ROW_NUMBER() OVER (PARTITION BY NULL ORDER BY (SELECT NULL)) AS num
FROM BigDataBase.Information_Schema.Columns c
)a
WHERE [num] <
(
SELECT DATEDIFF(MONTH,@startDate,@endDate) b
)
) n
CROSS JOIN
(
SELECT @startDate firstdate
) b
) a INNER JOIN
(
SELECT [EventId],[FirstOccurance_Month],[LastOccurance_Month]
FROM LogTable
) b
ON a.[DateTime] >= DATEADD(MONTH, DATEDIFF(MONTH, 0, b.[FirstOccurance_Month]), 0)
AND a.[DateTime] <= DATEADD(MONTH, DATEDIFF(MONTH, 0, b.[LastOccurance_Month]), 0)
ORDER BY b.[EventId],a.[DateTime]