2

我有一个表格,其中每个行项目都包含一个单元编号、日期戳和床位数。每天为每个单元创建一个包含床位数量的记录。

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。相反,grouper 值是 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
4

2 回答 2

2

您可以使用lag检查前一行的床位值是否相同,并获取作为 Grouper 列的运行总和。

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

此后,使用每个组的 min 和 max 很容易获得开始和结束日期。

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
于 2017-03-07T19:33:42.077 回答
0

这是一个间隙和孤岛问题,您可以使用两个row_number()s 来解决它,如下所示:

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 |
+------+------+------------+------------+
于 2017-03-07T19:46:53.963 回答