2017-01-05 10 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 | 
+-------------------------+------+ 

コード連続した日付の最小値と最大値を見つけるには、名前列を使用して結果をグループ化し、最小値と最大値を1つの列に 'to and from'文字列としてリストします。

連続した日付のみを表示する際に問題が発生しています。上記の3番目のエントリは、それ以前のエントリの 'A'の日付範囲と連続していないため、独自のエントリを取得することに注意してください。

編集注:これは、LAG機能の使用を許可していないSQL Server 2008に固有です。


EDIT 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。同じ名前の連続する日付の間の何日。

アイランド。計算された日に名前を追加します。

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

第2部:各島の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

2008年には利用できないLAGの使用だと思います。 – Sparked

+0

テーブルに固有の識別子がある場合は、解決策があります。 http://stackoverflow.com/questions/22188514/alternate-of-lead-lag-function-in-sql-server-2008 – McNets

関連する問題