2017-03-07 3 views
2

Ich habe eine Tabelle, in der jede Position eine Einheit #, Datumsstempel und Bettanzahl enthält. Für jede Einheit mit der Anzahl der Betten wird jeden Tag ein Datensatz erstellt.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 

Ich bin versucht, die Daten zu nehmen und eine Tabelle wie die unten erstellen.

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 

Das Problem ist, dass die Zeilen mit 24 Betten kombiniert werden, diese Ergebnisse zu erhalten.

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 

Ich versuchte DENSE_RANK mit einem Ranking zuweisen als Gruppierungsnummer zu verwenden, um die Instanzen der 24 Betten zu trennen. Ich möchte die Grouper-Werte 1,2,2,3,4,4 haben. Stattdessen sind die Grouper-Werte 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

Sie könnte interessiert sein an [* diese Antwort auf, "Lösen von Lücken und Inseln" mit row_number() und d ense_rank()? *] (http://dba.stackexchange.com/a/167069/2639) –

Antwort

2

können Sie lag verwenden um zu überprüfen, ob die vorherige Zeile denselben Wert für Betten und die laufende Summe als Grouper Spalte erhalten.

Danach, um die Start- und Enddaten ist einfach mit min und max für jede Gruppe zu bekommen.

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 

Wenn Sie nicht über eine Grouper Spalte brauchen, aber nur die Start- und Enddaten, kann dies mit Unterschied von Zeilennummern erfolgen.

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

Der letzte funktionierte! Vielen Dank! Ich spielte eine ganze Weile mit RANK, DENSE_RANK und ROW_NUMBER herum. – mckeyes

0

Dies ist ein Lücken und Inseln Problem, können Sie es wie so mit zwei row_number() s lösen:

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 Demo: http://rextester.com/IJXC7931

kehrt:

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