几年后我回到mysql并遇到了问题。我有一个有效的查询,但我对如何更好地优化它感到迷茫。
以下是查询:
select
u.id as 'User',
count(distinct tr.id) as Trips,
count(distinct ti.id) as 'Trip Items'
from
users u
inner join
user_emails ue on u.id = ue.user_id
inner join
trips tr on tr.user_id = u.id
inner join
trip_items ti on ti.trip_id = tr.id
where
ue.verified = true and ue.is_primary = true
and
tr.created_at between '2017-02-01 00:00:00' and '2017-02-01 00:59:59'
group by 1
having Trips < 30
我基本上需要计算所有旅行和旅行项目..但仅适用于在给定日期范围内有30次或更少旅行的用户。现在,我正在通过用户对结果进行分组,然后执行“拥有”来实现这一目标。我在非索引字段(created_at)上查看数百万条结果。理想情况下,我想获得一排总行程和总行程项目。但在查询期间仍然应用“用户少于30次旅行”。这可能吗? :)
只是一个快速编辑,我已经尝试了解其他解决方案,但我有点迷失在我应该寻找的东西上。我不是在寻找解决方案,也许只是“去检查一下并尝试一下”。
答案 0 :(得分:1)
count(distinct)
可能很贵。尝试在执行join
之前聚合。我认为以下工作(假设不同的旅行之间不共享项目):
select u.id as `User`, tr.Trips, tr.items
from users u inner join
user_emails ue
on u.id = ue.user_id inner join
(select tr.user_id, count(*) as Trips, sum(items) as items
from trips tr join
(select ti.trip_id, count(*) as items
from trip_items ti
group by ti.trip_id
) ti
on ti.trip_id = tr.id
where tr.created_at >= '2017-02-01' and tr.created_at < '2017-02-01 01:00:00'
group by tr.user_id
having trips < 30
) tr
on tr.user_id = u.id inner join
where ue.verified = true and ue.is_primary = true
group by 1