2016-04-15 24 views
0

我在我的SQL Server數據庫的數據結構:如何從一行T-SQL的樞軸數據列

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; 

SQL Fiddle

這是假定您的日期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); 

SQL Fiddle

結果:

| 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 | 
+0

謝謝你,你很來。 – user1453232

+0

你剛剛謝謝我,然後歡迎你自己? :) –