mysql - Mysql:按最新查询优化分组
问题描述
我一直在优化这个查询。我希望我没有过度简化我的例子。
我有一张表格,以下表格:
运动员:
id, name, team_id
测量:
id, type, value, athlete_id, measured_at
我需要找到最新、最旧和倒数第二个测量值,因此我编写了以下查询:
select
m.athlete_id,
m.`type`,
(
select ml.`value`
from measurements ml
where ml.athlete_id = m.athlete_id
and ml.`type` = m.`type`
order by ml.measured_at desc limit 1
)
as latest_record,
(
select mo.`value`
from measurements mo
where mo.athlete_id = m.athlete_id
and mo.`type` = m.`type`
order by mo.measured_at asc limit 1
)
as oldest_record,
(
select mp.`value`
from measurements mp
where mp.athlete_id = m.athlete_id
and mp.`type` = m.`type`
order by mp.measured_at desc limit 1 offset 1
)
as penultimate_record
from measurements m
group by m.athlete_id, m.`type`;
这得到了我所要求的一切,但它不是高性能的,或者至少我需要修改我的应用程序中的其他东西,如果它必须这么慢的话。
我还尝试将选择逻辑移动到左侧连接,例如。
left join lateral
(
SELECT mlr.id as measurement_id, mlr.value as `value`
FROM measurements mlr
WHERE mlr.athlete_id = s.id
and mlr.type = v.type
ORDER BY mlr.measured_at ASC LIMIT 1
)
as latest_record on m.id = latest_record.measurement_id
但这与上述速度相似。我还尝试将数据库索引放在列上,但没有看到任何改进。
有没有我可以放在这里的索引,或者用另一种方法来编写它以使查询更好地执行?
谢谢
解决方案
我建议条件聚合:
select m.athlete_id, m.`type`,
max(case when seqnum_desc = 1 then value end) as latest_record,
max(case when seqnum_asc = 1 then value end) as oldest_record,
max(case when seqnum_desc = 2 then value end) as penultimate_record
from (select m.*,
row_number() over (partition by athlete_id, type order by measured_at asc) as seqnum_asc,
row_number() over (partition by athlete_id, type order by measured_at desc) as seqnum_desc
from measurements m
) m
group by m.athlete_id, m.`type`;
这仍然会产生分组的开销——这可能很昂贵。您可能需要在measures(athlete_id, type, measured_at)
.
推荐阅读
- java - 不推荐使用 HttpMethod getResponseBodyAsString 但为什么
- automation - Protractor Chrome 无头混合内容问题
- android - 无法使用 Androidx Artifacts 在 Android Studio 3.3 上成功构建新项目?
- ruby - Sinatra 中的嵌套 Liquid 模板
- reactjs - redux-thunk:通过 store.dispatch() 调用操作时缺少属性“类型”
- c - scanf() 尝试输入带或不带空格的字符串时关闭程序
- python - 在命名元组中使用下划线
- ssl - 无法在 Mac 上创建开发者证书
- erlang - 将 C++ 共享库作为 Erlang 端口驱动程序打开时出错
- javascript - How to splice several strings