通过检查上一行中的值获取最新行
Get latest row by checking a value in previous row
我想获取处于失败状态的最新行作业,但同一作业的前一行应该是成功 .我不想获得不断失败的工作记录。我正在使用 MySQL 版本 5.6.10
来源Tablejob_status
:
Job_name start_date end_date status
A 8/3/2022 12 PM 8/3/2022 1.30 PM failed
B 8/3/2022 12 PM 8/3/2022 1.00 PM failed
C 8/3/2022 3 PM 8/3/2022 3.10 PM success
B 8/3/2022 3 PM 8/3/2022 3.30 PM failed
C 8/3/2022 3 PM 8/3/2022 3.20 PM success
A 8/3/2022 2 PM 8/3/2022 2.10 PM success
A 8/3/2022 3 PM 8/3/2022 3.20 PM failed
期望输出:
Job_name start_date end_date status
A 8/3/2022 3 PM 8/3/2022 3.20 PM failed
我正在使用以下查询,不确定如何检查以前的 运行。
select distinct(*)
from job_status
where status = 'failed'
order by start_date desc
就性能而言,这不会赢得任何奖牌,但是...
select *
from t
where status = 'failed'
and coalesce((
-- previous status
-- coalesce is needed when there is no previous row
select status
from t as x
where x.job_name = t.job_name and x.start_date < t.start_date
order by x.start_date desc
limit 1
), 'success') = 'success'
and not exists (
-- no next record exists
select 1
from t as x
where x.job_name = t.job_name and x.start_date > t.start_date
)
未经测试,但您应该能够用一个相关的 exists 子句来表达:
select *
from job_status s
where s.status='failed'
and exists (
select * from job_status s2
where s2.job_name = s.job_name
and s2.status = 'success'
and s2.end_date < s.end_date
order by s2.end_date desc
limit 1)
order by start_date desc;
问题的任何解决方案都将取决于一些非常重要的假设,这些假设应该在问题中得到解决:
- 状态只能从失败到成功
- “最新”是指最大的行 end_date
- end_date 属性是 DATETIME 类型
- end_date、job_status 和 job_name 的组合是独一无二的
如果其中任何一个不是这种情况,那么 SQL 中的解决方案是不可能的(并且在没有其他信息的情况下使用过程语言仍然非常困难)。
同样,这不是一个有效的函数,尽管它会受益于上面 4 中描述的组合索引的存在,顺序为 job_status、job_name、end_date (否则对于索引来说这将是一个糟糕的选择)....
SELECT c.*
FROM (
SELECT a.job_name, MAX(b.end_date) AS last_fail
FROM job_status a
JOIN job_status b
ON a.job_name=b.job_name
WHERE a.status='success'
AND b.status='failed'
GROUP BY a.job_name
) ilv
JOIN job_status c
ON ilv.job_name=c.job_name
AND ilv.last_fail=c.end_date
真的,这只是分组最大问题的一个变体,在这里仍然每周被问一次,并且 its own chapter in the manual。
根据数据的分布和行数,更有效的解决方案可能是读取 table 中的每一行,按 job_name、[=38= 排序](降序)和 end_date 然后 return 紧接在每个“成功”之后的条目,其中 job_name 匹配前一行。这应该是可能的......
SELECT job_name, job_status, start_date, end_date
FROM (
SELECT @prev_status AS prev_status, @prev_job_name AS prev_job_name,
a.*,
@prev_status:=a.status AS currstatus,
@prev_job_name:=a.job_name AS currjobname
FROM (
SELECT b.*
FROM job_status b
ORDER BY b.job_name, b.status DESC, d.end_date DESC
) a
) c
WHERE c.prev_status-'success'
AND c.job_status='failed'
AND c.prev_job_name=job_name
我想获取处于失败状态的最新行作业,但同一作业的前一行应该是成功 .我不想获得不断失败的工作记录。我正在使用 MySQL 版本 5.6.10
来源Tablejob_status
:
Job_name start_date end_date status
A 8/3/2022 12 PM 8/3/2022 1.30 PM failed
B 8/3/2022 12 PM 8/3/2022 1.00 PM failed
C 8/3/2022 3 PM 8/3/2022 3.10 PM success
B 8/3/2022 3 PM 8/3/2022 3.30 PM failed
C 8/3/2022 3 PM 8/3/2022 3.20 PM success
A 8/3/2022 2 PM 8/3/2022 2.10 PM success
A 8/3/2022 3 PM 8/3/2022 3.20 PM failed
期望输出:
Job_name start_date end_date status
A 8/3/2022 3 PM 8/3/2022 3.20 PM failed
我正在使用以下查询,不确定如何检查以前的 运行。
select distinct(*)
from job_status
where status = 'failed'
order by start_date desc
就性能而言,这不会赢得任何奖牌,但是...
select *
from t
where status = 'failed'
and coalesce((
-- previous status
-- coalesce is needed when there is no previous row
select status
from t as x
where x.job_name = t.job_name and x.start_date < t.start_date
order by x.start_date desc
limit 1
), 'success') = 'success'
and not exists (
-- no next record exists
select 1
from t as x
where x.job_name = t.job_name and x.start_date > t.start_date
)
未经测试,但您应该能够用一个相关的 exists 子句来表达:
select *
from job_status s
where s.status='failed'
and exists (
select * from job_status s2
where s2.job_name = s.job_name
and s2.status = 'success'
and s2.end_date < s.end_date
order by s2.end_date desc
limit 1)
order by start_date desc;
问题的任何解决方案都将取决于一些非常重要的假设,这些假设应该在问题中得到解决:
- 状态只能从失败到成功
- “最新”是指最大的行 end_date
- end_date 属性是 DATETIME 类型
- end_date、job_status 和 job_name 的组合是独一无二的
如果其中任何一个不是这种情况,那么 SQL 中的解决方案是不可能的(并且在没有其他信息的情况下使用过程语言仍然非常困难)。
同样,这不是一个有效的函数,尽管它会受益于上面 4 中描述的组合索引的存在,顺序为 job_status、job_name、end_date (否则对于索引来说这将是一个糟糕的选择)....
SELECT c.*
FROM (
SELECT a.job_name, MAX(b.end_date) AS last_fail
FROM job_status a
JOIN job_status b
ON a.job_name=b.job_name
WHERE a.status='success'
AND b.status='failed'
GROUP BY a.job_name
) ilv
JOIN job_status c
ON ilv.job_name=c.job_name
AND ilv.last_fail=c.end_date
真的,这只是分组最大问题的一个变体,在这里仍然每周被问一次,并且 its own chapter in the manual。
根据数据的分布和行数,更有效的解决方案可能是读取 table 中的每一行,按 job_name、[=38= 排序](降序)和 end_date 然后 return 紧接在每个“成功”之后的条目,其中 job_name 匹配前一行。这应该是可能的......
SELECT job_name, job_status, start_date, end_date
FROM (
SELECT @prev_status AS prev_status, @prev_job_name AS prev_job_name,
a.*,
@prev_status:=a.status AS currstatus,
@prev_job_name:=a.job_name AS currjobname
FROM (
SELECT b.*
FROM job_status b
ORDER BY b.job_name, b.status DESC, d.end_date DESC
) a
) c
WHERE c.prev_status-'success'
AND c.job_status='failed'
AND c.prev_job_name=job_name