我的SQL Server数据库中有这个数据结构:
User FmDate ToDate
------------------------------------
Andy 1/10 1/15
Baey 1/14 1/18
Christy 1/17 2/18
日期是自然日的范围,如何编写t-sql以像excel一样转动它们,如图所示:
Andy 1/10
Andy 1/11
Andy 1/12
Andy 1/13
Andy 1/14
Andy 1/15
Baey 1/14
Baey 1/15
Baey 1/16
Baey 1/17
Baey 1/18
Christy 1/17
Christy 1/18
答案 0 :(得分:1)
您可以使用tally table生成从FmDate
到ToDate
的日期
DECLARE @range INT;
SELECT @range = MAX(DATEDIFF(DAY, FmDate, ToDate)) + 1 FROM tbl;
;WITH E1(N) AS( -- 10 ^ 1 = 10 rows
SELECT 1 FROM(VALUES (1),(1),(1),(1),(1),(1),(1),(1),(1),(1))t(N)
),
E2(N) AS(SELECT 1 FROM E1 a CROSS JOIN E1 b), -- 10 ^ 2 = 100 rows
E4(N) AS(SELECT 1 FROM E2 a CROSS JOIN E2 b), -- 10 ^ 4 = 10,000 rows
CteTally(N) AS(
SELECT TOP(@Range) ROW_NUMBER() OVER(ORDER BY(SELECT NULL))
FROM E4
),
CteDates([User], dt) AS(
SELECT t.[User], DATEADD(DAY, N-1, FmDate)
FROM tbl t
CROSS JOIN CteTally ct
WHERE DATEADD(DAY, N-1, FmDate) <= ToDate
)
SELECT *
FROM CteDates
ORDER BY [User], dt;
这假定您的日期为DATE
格式。
在编辑之前,您的预期结果是一个透视版本。
要调整上述结果,请使用dynamic crosstab。将上述结果插入临时表进行处理:
IF OBJECT_ID('tempdb..##tembTbl') IS NOT NULL BEGIN
DROP TABLE ##tempTbl
END
DECLARE @range INT;
SELECT @range = MAX(DATEDIFF(DAY, FmDate, ToDate)) + 1 FROM tbl;
;WITH E1(N) AS( -- 10 ^ 1 = 10 rows
SELECT 1 FROM(VALUES (1),(1),(1),(1),(1),(1),(1),(1),(1),(1))t(N)
),
E2(N) AS(SELECT 1 FROM E1 a CROSS JOIN E1 b), -- 10 ^ 2 = 100 rows
E4(N) AS(SELECT 1 FROM E2 a CROSS JOIN E2 b), -- 10 ^ 4 = 10,000 rows
CteTally(N) AS(
SELECT TOP(@Range) ROW_NUMBER() OVER(ORDER BY(SELECT NULL))
FROM E4
),
CteDates([User], dt) AS(
SELECT t.[User], DATEADD(DAY, N-1, FmDate)
FROM tbl t
CROSS JOIN CteTally ct
WHERE DATEADD(DAY, N-1, FmDate) <= ToDate
)
SELECT *
INTO ##tempTbl
FROM CteDates;
DECLARE @sql NVARCHAR(MAX) = '';
SELECT @sql =
'SELECT
[User]' + CHAR(10)
SELECT @sql = @sql +
' , MAX(CASE WHEN dt = ''' + CONVERT(VARCHAR(8), dt, 112) + ''' THEN ''Y'' ELSE '''' END) AS ' + QUOTENAME(CONVERT(VARCHAR(5), dt, 101)) + CHAR(10)
FROM (SELECT DISTINCT dt FROM ##tempTbl) t
ORDER BY dt
SELECT @sql = @sql +
'FROM ##tempTbl
GROUP BY [User];'
PRINT (@sql);
EXEC (@sql);
<强>结果:强>
| User | 01/10 | 01/11 | 01/12 | 01/13 | 01/14 | 01/15 | 01/16 | 01/17 | 01/18 |
|---------|-------|-------|-------|-------|-------|-------|-------|-------|-------|
| Andy | Y | Y | Y | Y | Y | Y | | | |
| Baey | | | | | Y | Y | Y | Y | Y |
| Christy | | | | | | | | Y | Y |