我有一个包含以下列的表:(Car, User, Location, Time, Type)
类型可以是:
- "出">是否接受用户的租车请求
- '在'当用户停止使用汽车并将其注册回系统时
- "否认">当租车被拒绝访问时
所以关于类型的记录顺序应该是OUT-IN(时间升序)
存在不一致的数据,其中可能存在具有相同的汽车,用户,位置和类型值的几行,如以下
<表类>
汽车
用户
位置时间类型 tbody><<tr>1 本 芝加哥td 2022-02-12 03:12:45 //应该被删除 1本 芝加哥td> 2022-02-12 04:12:45 //应该被删除 2山姆 纽约 2022-02-12 04:42:45 出 1本 芝加哥td> 2022-02-12 04:50:00 //应该保持 1山姆 纽约 2022-02-12 07:32:12 1本 芝加哥td> 2022-02-12 08:18:45 //应该删除 3 米娅 圣法郎 2022-02-12 09:12:43 出 1本 芝加哥td> 2022-02-12 09:27:23 //应该保持 表类>
您可以在Type
字段上使用一对窗口函数:
LAG
,检索前一个值LEAD
,检索下一个值
这些窗口函数将根据涉及以下字段的特定分区按此顺序应用:User
,Car
,Location
。
获得这些值后,当字段Type
满足以下条件之一时,就可以检索行:
Type = OUT
andTypeNext = IN
(lastOUT
)Type = IN
和TypePrev = IN
,而不是TypeNext = IN
(最后一个IN
)Type = DENIED
如果在近行上有更复杂的条件,可以通过这三个计算值来处理它们。
WITH cte AS (
SELECT Car,
User,
Location,
Time,
LAG(Type) OVER(
PARTITION BY User, Car, Location
ORDER BY Time) AS TypePrev,
Type,
LEAD(Type) OVER(
PARTITION BY User, Car, Location
ORDER BY Time) AS TypeNext
FROM rent_logs
)
SELECT Car,
User,
Location,
Time,
Type
FROM cte
WHERE (Type = 'OUT' AND TypeNext = 'IN')
OR (Type = 'IN' AND TypePrev = 'IN' AND (TypeNext = 'OUT' OR TypeNext IS NULL))
OR (TypePrev IS NULL AND TypeNext IS NULL)
OR (Type = 'DENIED')
ORDER BY User,
Time
在这里查看SQL提琴
如果你想玩一点,了解它是如何工作的,在小提琴链接的中间结果,我建议从注释行中删除注释,并在WHERE
子句中注释条件。