2017-03-07 50 views
2

我有一個表,其中每個行項目包含單元#,日期戳和牀位數。每個有牀位數的單位都會創建一條記錄。SQL Server DENSE_RANK()

Unit DateTime Beds 
---------------------- 
ICU 2011-03-23 12 
ICU 2011-03-24 24 
ICU 2011-03-25 24 
ICU 2011-03-26 35 
ICU 2011-03-27 24 
ICU 2011-03-28 24 

我正在嘗試取數據並創建一個如下所示的表。

Unit Beds StartDate EndDate 
------------------------------ 
ICU 12 2011-03-23 2011-03-23 
ICU 24 2011-03-24 2011-03-25 
ICU 35 2011-03-26 2011-03-26 
ICU 24 2011-03-27 2011-03-28 

問題是,有24張牀的行正在合併以獲得這些結果。

Unit Beds StartDate EndDate 
------------------------------ 
ICU 12 2011-03-23 2011-03-23 
ICU 24 2011-03-24 2011-03-28 
ICU 35 2011-03-26 2011-03-26 

我嘗試使用DENSE_RANK來指定一個排名以用作分組號碼來分隔24張牀的實例。我想石斑魚的價值是1,2,2,3,4,4。相反,石斑魚的值是1,2,2,3,2,2。

SELECT DENSE_RANK() OVER(PARTITION BY Unit ORDER BY Beds) AS Grouper, 
Unit, DateTime, Beds 
FROM StatsLocation 

Grouper Unit DateTime Beds 
------------------------------- 
1  ICU 2011-03-23 12 
2  ICU 2011-03-24 24 
2  ICU 2011-03-25 24 
3  ICU 2011-03-26 35 
2  ICU 2011-03-27 24 
2  ICU 2011-03-28 24 
+0

你可能感興趣的是[*這個答案,用row_number()和d解決「間隙和島嶼」問題ense_rank()?*](http://dba.stackexchange.com/a/167069/2639) –

回答

2

您可以使用lag檢查上一行是否有牀相同的值,並獲得運行總和爲石斑魚列。

SELECT SUM(COL) OVER(PARTITION BY Unit ORDER BY DateTime) as Grouper,Unit,DateTime,Beds 
FROM (
SELECT CASE WHEN lag(beds) OVER(PARTITION BY Unit ORDER BY DateTime)=beds then 0 ELSE 1 END AS col, 
Unit, DateTime, Beds 
FROM StatsLocation 
) X 

此後,要獲得開始和結束日期很容易,每個組的最小和最大值。

WITH CTE AS( 
SELECT SUM(COL) OVER(PARTITION BY Unit ORDER BY DateTime) as Grouper,Unit,DateTime,Beds 
FROM (SELECT CASE WHEN lag(beds) OVER(PARTITION BY Unit ORDER BY DateTime)=beds then 0 ELSE 1 END AS col, 
     Unit, DateTime, Beds 
     FROM StatsLocation) t 
) 
SELECT UNIT,BEDS,MIN(DATETIME) AS STARTDATE,MAX(DATETIME) AS ENDDATE 
FROM CTE 
GROUP BY UNIT,BEDS,GROUPER 

如果您不需要一個石斑魚列,但只是開始和結束日期,這可以通過行號的差異來完成。

SELECT UNIT,BEDS,MIN(DATETIME) AS STARTDATE,MAX(DATETIME) AS ENDDATE 
FROM (
SELECT ROW_NUMBER() OVER(PARTITION BY Unit ORDER BY Dt) 
    - ROW_NUMBER() OVER(PARTITION BY Unit,Beds ORDER BY Dt) AS Grouper, 
Unit, Dt, Beds 
FROM StatsLocation) T 
GROUP BY UNIT,BEDS,GROUPER 
+0

最後一個工作!謝謝!我在RANK,DENSE_RANK和ROW_NUMBER上擺弄了很長一段時間。 – mckeyes

0

這是一個空白和島嶼的問題,您可以使用兩個row_number()就像這樣解決這個問題:

select 
    Unit 
    , Beds 
    , StartDate = min(DateTime) 
    , EndDate = max(DateTime) 
from (
    select * 
    , rn_x = row_number() over (partition by unit order by [datetime]) 
    , rn_y = row_number() over (partition by unit, beds order by [datetime]) 
    from t 
    ) as s 
group by Unit, Beds, rn_x-rn_y 
order by Unit, StartDate 

rextester演示:http://rextester.com/IJXC7931

回報:

+------+------+------------+------------+ 
| Unit | Beds | StartDate | EndDate | 
+------+------+------------+------------+ 
| ICU | 12 | 2011-03-23 | 2011-03-23 | 
| ICU | 24 | 2011-03-24 | 2011-03-25 | 
| ICU | 35 | 2011-03-26 | 2011-03-26 | 
| ICU | 24 | 2011-03-27 | 2011-03-28 | 
+------+------+------------+------------+