sql - SQL在根据条件将一列拆分为2时将表自身连接起来
问题描述
我有一个看起来像这样的表:
+-----------------------------+
|tag|state|time |
+-----------------------------+
|AAA|GOOD |2020/03/19 16:00:00|
+-----------------------------+
|BBB|GOOD |2020/03/19 16:00:00|
+-----------------------------+
|BBB|BAD |2020/03/19 15:00:00|
+-----------------------------+
|CCC|HLTHY|2020/03/19 14:00:00|
+-----------------------------+
|AAA|BAD |2020/03/19 13:00:00|
+-----------------------------+
|CCC|UNHLT|2020/03/19 12:00:00|
+-----------------------------+
etc...
我需要进行一个查询,显示标签的状态何时变坏以及何时再次恢复正常,因此输出应如下所示:
+-------------------------------------------------+
|tag|state|startTime |stopTime |
+-------------------------------------------------+
|AAA|BAD |2020/03/19 13:00:00|2020/03/19 16:00:00|
+-------------------------------------------------+
|BBB|BAD |2020/03/19 15:00:00|2020/03/19 16:00:00|
+-------------------------------------------------+
|CCC|UNHLT|2020/03/19 12:00:00|2020/03/19 14:00:00|
+-------------------------------------------------+
etc...
我现在的查询如下所示:
SELECT A.tag, A.state, A.startTime, B.stopTime
FROM
(SELECT tag, state, time as startTime
FROM table
WHERE state LIKE 'BAD' or state LIKE 'UNHLT')A
JOIN
(SELECT tag, state, time as stopTime
FROM table
WHERE state LIKE 'GOOD' or state like 'HLTHY')B
ON (A.tag = B.tag and A.time < B.time)
但是,此查询显示无序结果,其中 startTimes 完全无序,并且大量 stopTimes 重复,如下所示:
+-------------------------------------------------+
|tag|state|startTime |stopTime |
+-------------------------------------------------+
|AAA|BAD |2020/03/12 08:00:00|2020/03/19 16:00:00|
+-------------------------------------------------+
|AAA|BAD |2020/03/12 09:00:00|2020/03/19 16:00:00|
+-------------------------------------------------+
|AAA|BAD |2020/03/12 08:00:00|2020/03/18 14:00:00|
+-------------------------------------------------+
|BBB|BAD |2020/03/12 11:00:00|2020/03/19 16:00:00|
+-------------------------------------------------+
|BBB|BAD |2020/03/13 07:00:00|2020/03/19 16:00:00|
+-------------------------------------------------+
etc...
我需要对我的查询进行哪些更改,以使其输出变得像所需的那样?
解决方案
我想你只是想要lag()
:
select t.*
from (select t.*,
lag(state) over (partition by tag order by time) as prev_state,
min(case when state not in ('BAD', 'UNHLT') then time end) over (partition by tag order by time desc) as next_good_time
from t
) t
where state in ('BAD', 'UNHLT') and
prev_state not in ('BAD', 'UNHLT')
推荐阅读
- php - laravel 问题中的雄辩关系
- javascript - 将无限数量的参数传递给 sort() 函数
- html5-video - 在 Chrome 中单击 HTML5 视频上的特定位置
- angular - 'ion-tab' 不是已知元素
- javafx - 如何使用 FileChooser 从文件中获取数据(项目 ID、项目名称、项目价格)并在组合框中列出项目 ID?如何将标签与选择匹配?
- python - 将函数应用于单个 R data.frame 列:lapply 和 apply 不起作用 - 寻找与 Python 的 DataFrame.apply(...) 等效的 R
- serialization - 当我将 .appxupload 而不是 .appxbundle 上传到 HockeyApp 时出现序列化异常
- hibernate - 线程“主”org.hibernate.InvalidMappingException 中的异常:无法从资源 emp.hbm.xml 解析映射文档
- javascript - 打开 HTML 文件时出现空白页
- node.js - 如何存根或模拟我正在尝试测试的函数中所需的另一个节点模块