2017-03-07 46 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 | 
+------+------+------------+------------+