假设数据
ID Date Mode
1 2019-09-20 09:28 IN
2 2019-09-20 19:00 IN
3 2019-09-20 19:00 IN
4 2019-09-20 19:00 IN
5 2019-09-20 19:01 IN
6 2019-09-20 19:01 IN
7 2019-09-20 19:01 Out
8 2019-09-20 20:28 IN
9 2019-09-20 20:35 IN
10 2019-09-20 20:50 Out
11 2019-09-20 20:55 Out
12 2019-09-20 21:30 IN
转换为从最小入住到最大退房的期间的行
我使用迭代来获得期望的结果,但想要优化查询(设置基准或CTE)以提高性能,
这就是我想要的
ID DateIN ID DateOut
01 2019-09-20 09:28 07 2019-09-20 19:01
08 2019-09-20 20:28 11 2019-09-20 20:55
这是一个基于孤岛的问题。
首先,可以使用以下查询生成连续记录组:
SELECT [Mode], MIN(id) min_id, MAX(id) max_id, MIN([Date]) min_date, MAX([Date]) max_date
FROM (
SELECT
id,
[Date],
[Mode],
ROW_NUMBER() OVER(ORDER BY [Date]) rn1,
ROW_NUMBER() OVER(PARTITION BY [Mode] ORDER BY [Date]) rn2
FROM mytable
) x
GROUP BY [Mode], (rn1 - rn2)
这产生了:
模式| min_id | max_id | min_date | max_date:--- | -----:| -----:| :--------------- | :---------------IN | 1 | 6 | 2019-09-20 09:28 | 2019-09-20 19:01出| 7 | 7 | 2019-09-20 19:01 | 2019-09-20 19:01IN | 8 | 9 | 2019-09-20 20:28 | 2019-09-20 20:35出| 10 | 11 | 2019-09-20 20:50 | 2019-09-20 20:55IN | 12 | 12 | 2019-09-20 21:30 | 2019-09-20 21:30
然后,您可以将此查询转换为cte并对其进行自我联接以生成预期的结果集:
WITH cte AS (
SELECT [Mode], MIN(id) min_id, MAX(id) max_id, MIN([Date]) min_date, MAX([Date]) max_date
FROM (
SELECT
id,
[Date],
[Mode],
ROW_NUMBER() OVER(ORDER BY [Date]) rn1,
ROW_NUMBER() OVER(PARTITION BY [Mode] ORDER BY [Date]) rn2
FROM mytable
) x
GROUP BY [Mode], (rn1 - rn2)
)
SELECT c1.min_id IdIn, c1.min_date DateIN, c2.max_id IdOut, c2.max_date DateOut
FROM cte c1
INNER JOIN cte c2
ON c1.mode = 'IN'
AND c2.mode = 'Out'
AND c2.min_id = c1.max_id + 1
输出:
IdIn | DateIN | IdOut |约会---: :--------------- | ----:| :---------------1 | 2019-09-20 09:28 | 7 | 2019-09-20 19:018 | 2019-09-20 20:28 | 11 | 2019-09-20 20:55