2017-03-07 16 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를 사용하여 "Gaps and Islands"에 대한 [*이 대답에 관심이있을 수 있습니다. 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 | 
+------+------+------------+------------+