SQL 服务器 DENSE_RANK()
SQL Server DENSE_RANK()
我有一个 table,其中每个行项目都包含一个单元号、日期戳和床位数量。每天为每个单元创建一个记录,其中包含床位数量。
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
我正在尝试获取数据并创建如下所示的 table。
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
您可以使用 lag
检查前一行是否具有相同的 beds 值,并获得 运行 总和作为 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
此后,使用每个组的最小值和最大值即可轻松获取开始和结束日期。
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
这是一个间隙和孤岛问题,您可以使用两个 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
returns:
+------+------+------------+------------+
| 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 |
+------+------+------------+------------+
我有一个 table,其中每个行项目都包含一个单元号、日期戳和床位数量。每天为每个单元创建一个记录,其中包含床位数量。
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
我正在尝试获取数据并创建如下所示的 table。
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
您可以使用 lag
检查前一行是否具有相同的 beds 值,并获得 运行 总和作为 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
此后,使用每个组的最小值和最大值即可轻松获取开始和结束日期。
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
这是一个间隙和孤岛问题,您可以使用两个 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
returns:
+------+------+------------+------------+
| 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 |
+------+------+------------+------------+