我需要创建一个输出,我每年有一行。
假设数据集是:
id | dateStart | dateEnd
1 | 2015-01-01 00:00:00.000 | 2015-03-31 00:00:00.000
2 | 2014-07-01 00:00:00.000 | 2014-08-31 00:00:00.000
...
我需要以下输出:
id | year-month
1 | 2015-01
1 | 2015-02
1 | 2015-03
2 | 2014-07
2 | 2014-08
输出可以是任何数据类型,因为我可以稍后更改它。 那是2015-01,以下是好的,“2015-01-01 00:00:00.000”,“2015-01-01”,“201501”,“2015 | jan”等。
注意我正在使用SQL Server 2005。
答案 0 :(得分:1)
这是一个使用递归CTE的方法:
with CTE as (
select id, dateStart as dte, dateEnd
from t
union all
select id, dateadd(month, 1, dte), dateEnd
from CTE
where dateadd(month, 1, dte) < dateEnd
)
select id, dte
from CTE;
您可以将最终结果转换为您喜欢的任何格式。例如:
select id, year(dte) * 10000 + month(dte) as yyyymm_int
或
select id, cast(year(dte) * 10000 + month(dte) as varchar(255)) as yyyymm
答案 1 :(得分:1)
生成计数表(只需确保在那里获得足够的行)。计数器将包含值0,1,2,.....n
。然后,您使用条件将此值添加为startDate
的月份,直到它大于endDate
:
DECLARE @t TABLE
(
id INT ,
dateStart DATETIME ,
dateEnd DATETIME
)
INSERT INTO @t
VALUES ( 1, '2015-01-01 00:00:00.000', '2015-03-31 00:00:00.000' ),
( 2, '2014-07-01 00:00:00.000', '2014-08-31 00:00:00.000' )
;WITH cte AS(SELECT -1 + ROW_NUMBER() OVER(ORDER BY t1.m) m
FROM(VALUES(0),(0),(0),(0),(0),(0),(0),(0),(0),(0))t1(m) CROSS JOIN
(VALUES(0),(0),(0),(0),(0),(0),(0),(0),(0),(0))t2(m))
SELECT t.id,
DATEADD(mm, c.m, t.dateStart) AS year_month
FROM cte c
JOIN @t t ON DATEADD(mm, c.m, t.dateStart) <= t.dateEnd
ORDER BY t.id, year_month
输出:
id year_month
1 2015-01-01 00:00:00.000
1 2015-02-01 00:00:00.000
1 2015-03-01 00:00:00.000
2 2014-07-01 00:00:00.000
2 2014-08-01 00:00:00.000
答案 2 :(得分:1)
在一个理想的世界中,你会有calendar table,那么你的查询就是:
SELECT t.id,
c.FirstDayOfMonth
FROM YourTable AS t
INNER JOIN dbo.Calendar c
ON c.FirstDayOfMonth >= t.DateStart
AND c.FirstDayOfMonth <= t.DateEnd
AND c.DayOfMonth = 1;
假设您没有日历表,那么您可以使用动态生成的数字列表(阅读this article了解更多信息)。以下将生成1-10,000的列表:
WITH N1 AS (SELECT N FROM (VALUES (1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) N (N)),
N2 (N) AS (SELECT 1 FROM N1 AS N1 CROSS JOIN N1 AS N2),
N3 (N) AS (SELECT 1 FROM N2 AS N1 CROSS JOIN N2 AS N2),
Numbers (Number) AS (SELECT ROW_NUMBER() OVER(ORDER BY N3.N) FROM N3)
SELECT * FROM Numbers;
然后您可以将其加入原始表格:
DECLARE @T TABLE (id INT, DateStart DATE, DateEnd DATE);
INSERT @T (ID, DateStart, DateEnd)
VALUES (1, '20150101', '20150331'), (2, '20140701', '20140831');
WITH N1 AS (SELECT N FROM (VALUES (1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) N (N)),
N2 (N) AS (SELECT 1 FROM N1 AS N1 CROSS JOIN N1 AS N2),
N3 (N) AS (SELECT 1 FROM N2 AS N1 CROSS JOIN N2 AS N2),
Numbers (Number) AS (SELECT ROW_NUMBER() OVER(ORDER BY N3.N) FROM N3)
SELECT t.ID,
[year-month] = DATEADD(MONTH, n.Number + DATEDIFF(MONTH, 0, t.DateStart), 0)
FROM @T AS t
INNER JOIN Numbers AS N
ON N.Number - 1 <= DATEDIFF(MONTH, t.DateStart, t.DateEnd);