2017-01-05 62 views
2

我有表,看起來像這樣:顯示日期範圍 - 差距和羣島

+------------+------+ 
| Date | Name | 
+------------+------+ 
| 2017-01-07 | A | 
| 2017-01-08 | A | 
| 2017-01-09 | A | 
| 2017-01-12 | A | 
| 2017-01-07 | B | 
| 2017-01-08 | B | 
| 2017-01-09 | B | 
+------------+------+ 

我希望能夠把它變成如下:

+-------------------------+------+ 
|  Date Range  | Name | 
+-------------------------+------+ 
| 2017-01-07 - 2017-01-09 | A | 
| 2017-01-07 - 2017-01-09 | B | 
| 2017-01-12    | A | 
+-------------------------+------+ 

代碼將僅查找連續日期的最小值和最大值,使用名稱列對結果進行分組,然後將最小和最大日期列爲一列中的「從和到」字符串。

我在嘗試僅列出連續日期時遇到問題。請注意,上面的第三個條目獲取它自己的條目,因爲它與先前條目中的「A」的日期範圍不連續。

編輯:請注意:這是特定於SQL Server 2008,它不允許使用LAG功能。


編輯2: 通過McNets提供的原來的答覆工作SQL Server 2012的精細我在這裏包含它,因爲它的更好,如果你有SQL Server 2012的開始。

;WITH CalcDiffDays AS 
(
    SELECT Date, Name, 
    CONCAT (Name, CAST(DATEDIFF(DAY, LAG(Date, 1, Date - 1) OVER (PARTITION BY Name ORDER BY Name, Date), Date) AS VARCHAR(10))) AS NumDays 
    FROM @tmpTable 
) 
SELECT CONCAT(CONVERT(VARCHAR(20), MIN(Date), 102), ' - ', CONVERT(VARCHAR(20), MAX(Date), 102)) AS [Data Range], Name 
FROM CalcDiffDays 
GROUP BY NumDays, Name; 
+1

[SQL移調行列不彙總(可能的重複http://stackoverflow.com/questions/41462218/sql-transpose-rows-to-columns -without-aggregate) – iamdave

回答

1

首先我給整個表添加了一個行號。

WITH RowN AS 
(
    SELECT Date, Name, ROW_NUMBER() OVER (ORDER BY Name, Date) RN 
    FROM #T 
) 

然後我加入了這個表格,只是爲了計算日期之間的日子。

,CalcDiffDays AS 
(
    SELECT RowN.Date, RowN.Name, 
     ISLAND = RowN.Name + 
     CASE 
      WHEN RowN.RN > 1 AND RowN.Name = R2.Name THEN CAST(DATEDIFF(day, R2.Date, RowN.Date) AS VARCHAR(20)) 
      ELSE '1' 
     END 
    FROM RowN 
     LEFT JOIN RowN R2 ON R2.RN = RowN.RN-1 
) 

GAPS。相同名稱的連續日期之間有多少天。

ISLANDS。通過將名稱添加到計算的天數。

+---------------------+------+---------+ 
|   Date  | Name | NumDays | 
+---------------------+------+---------+ 
| 07.01.2017 00:00:00 | A | A1 | 
+---------------------+------+---------+ 
| 08.01.2017 00:00:00 | A | A1 | 
+---------------------+------+---------+ 
| 09.01.2017 00:00:00 | A | A1 | 
+---------------------+------+---------+ 
| 12.01.2017 00:00:00 | A | A3 | 
+---------------------+------+---------+ 
| 07.01.2017 00:00:00 | B | B1 | 
+---------------------+------+---------+ 
| 08.01.2017 00:00:00 | B | B1 | 
+---------------------+------+---------+ 
| 09.01.2017 00:00:00 | B | B1 | 
+---------------------+------+---------+ 

第二部分:獲取每個島的MIN和MAX日期。

WITH RowN AS 
(
    SELECT Date, Name, ROW_NUMBER() OVER (ORDER BY Name, Date) RN 
    FROM #T 
) 
,CalcDiffDays AS 
(
    SELECT RowN.Date, RowN.Name, 
     ISLAND = RowN.Name + 
     CASE 
      WHEN RowN.RN > 1 AND RowN.Name = R2.Name THEN CAST(DATEDIFF(day, R2.Date, RowN.Date) AS VARCHAR(20)) 
      ELSE '1' 
     END 
    FROM RowN 
     LEFT JOIN RowN R2 ON R2.RN = RowN.RN-1 
)  
SELECT CONVERT(VARCHAR(20), MIN(Date), 102) + ' - ' + CONVERT(VARCHAR(20), MAX(Date), 102) AS [Data Range], Name 
FROM CalcDiffDays 
GROUP BY ISLAND, Name 
ORDER BY MIN(Date); 

+-------------------------+------+ 
|  Data Range  | Name | 
+-------------------------+------+ 
| 2017.01.07 - 2017.01.09 | A | 
+-------------------------+------+ 
| 2017.01.07 - 2017.01.09 | B | 
+-------------------------+------+ 
| 2017.01.12 - 2017.01.12 | A | 
+-------------------------+------+ 

可以點擊此處查看:http://rextester.com/MHLEEJ50479

+0

這顯然是正確的答案,適用於我的2012服務器。但是,在2008服務器(我需要的那臺服務器)上出現此錯誤:並行數據倉庫(PDW)功能未啓用。谷歌搜索表明這可能是服務器的錯誤? – Sparked

+0

我認爲這是使用LAG,它在2008年不可用。 – Sparked

+0

如果您的表具有唯一標識符,那麼有一種可能的解決方案。 http://stackoverflow.com/questions/22188514/alternate-of-lead-lag-function-in-sql-server-2008 – McNets