我有一个要加入的表,需要两个不同条件下的数据。查询当前看起来像(混淆表名/列名):
SELECT s.id, r.last_date, r.last_automatic_date,
FROM servers s
LEFT JOIN
(SELECT rb_standard.sid, MAX(log_datetime) as last_date, rb_auto.last_automatic_date
FROM ruby rb_standard
LEFT JOIN
(SELECT sid, MAX(log_datetime) as last_automatic_date
FROM ruby rb_auto
WHERE SUBSTRING(upload_string, 3, 1) = '2'
GROUP BY sid
) rb_auto ON rb_auto.sid = rb_standard.sid
GROUP BY sid, rb_auto.last_automatic_date
) r ON r.sid = s.id
这相对较快,并且可以满足我的要求。但是,它不是很可扩展,而且不清楚要完成什么。将其与较旧,慢得多的查询版本进行比较:
SELECT s.id,
(SELECT MAX(log_datetime)
FROM ruby
WHERE sid = s.id
GROUP BY sid
) AS last_date,
(SELECT MAX(log_datetime)
FROM ruby
WHERE sid = s.id AND
SUBSTRING(upload_string, 3, 1) = '2'
GROUP BY sid
) AS last_automatic_date
FROM servers s
这很简单,但是(预期)很慢。我希望有比这两种方法更好的解决方案,但是我没有看到它。
我要问的确切问题是,从给定datetime列中希望获得最大值的表中进行选择的最有效方法(从处理速度的角度来看),但是该值可能会在不同的条件...并且这些条件下的最大值还应该返回到结果集中吗?
P.S。该版本使用的是最新版本的MySQL,因此可以访问窗口功能等新功能。
答案 0 :(得分:1)
您似乎希望有条件聚合将两种聚合合并为一个:
SELECT s.id, r.last_date, r.last_automatic_date,
FROM servers s
LEFT JOIN
(
SELECT rb_standard.sid, MAX(log_datetime) as last_date,
-- compare a string to a string ('2'), not a numeric value (2) to avoid unneccessary typecasts
MAX(case when SUBSTRING(upload_string, 3, 1) = '2' then log_datetime end) as last_automatic_date
FROM ruby rb_standard
GROUP BY sid
) r ON r.sid = s.id
答案 1 :(得分:1)
第一个查询->优化用于从所有记录中获取数据,而第二个查询-> select中的选择优化用于尽可能快地获取前几行。
如果您要进行批处理,即使用这些行的输出来处理和更新数据,那么我将使用选项1
如果您的网页旨在尽快显示前几条记录,则将第二个选项与分页查询一起使用。
顺便说一句,如果您使用的是oracle,则还有一个优化可用于进一步调用select中的选择。标量子查询缓存。
但是在您的情况下,可以使用@dnoeth提供的解决方案修改现有查询,以使其表现更好。