简体   繁体   English

优化子查询,选择每组的最后一条记录

[英]Optimize sub-query selecting last record of each group

I have this query which is a dependant query and taking much execution time 我有这个查询,这是一个依赖查询,并花费很多执行时间

SELECT
  u.id,
  u.user_name,
  ifnull((select longitude from map where user_id = u.id order by map_id desc limit 1 ),0) as Longitude,
  ifnull((select latitude from map where user_id = u.id order by map_id desc limit 1 ),0) as Longitude,
  (select  created  from map  where user_id = 1  order by created desc   limit 1) as LatestTime
FROM users as u
WHERE id IN(SELECT
          user1_id FROM relation
        WHERE users.id = 1)
ORDER BY id;

I tried this query in (dependant) 我在(依赖)中尝试了此查询

SELECT
  u.id,
  u.user_name,
  m.map_id,
  m.longitude,
  m.latitude,
  m.Date as created
FROM users as u
  left join (select
           map_id,
           longitude,
           latitude,
           user_id,
           max(created) as `Date`
         from map
         group by user_id) as m
    on m.user_id = u.id
WHERE id IN(SELECT
          user1_id FROM relation
        WHERE users.id = 1)
ORDER BY id;

The problem is that the first query is dependent and working fine but taking much execution time. 问题在于,第一个查询是依赖的,可以正常工作,但是要花费很多执行时间。 With the second query the problem is that it is not fetching the latest created time. 对于第二个查询,问题在于它没有获取最新的创建时间。 Now i want to optimise this query. 现在,我想优化此查询。 The theme is that in subquery i am first making group then i am trying to get the last record of each group. 主题是,在子查询中,我首先创建组,然后尝试获取每个组的最后一条记录。 and here is the tables structure. 这是表格结构。

users : id , user_name
map   : map_id ,  user_id ,longitude , latitude, created 
relations : id , user1_id , user2_id , relation

Where performance is needed, subqueries in the SELECT clause are indeed a pain and have to be banished :) 在需要性能的地方, SELECT子句中的子查询确实很痛苦,必须将其放逐:)

You can rewrite this part: 您可以重写此部分:

SELECT
    u.id,
    u.user_name,
    ifnull((select longitude from map where user_id = u.id order by map_id desc limit 1 ),0) as Longitude,
    ifnull((select latitude from map where user_id = u.id order by map_id desc limit 1 ),0) as Longitude,
    (select  created  from map  where user_id = 1  order by created desc   limit 1) as LatestTime
FROM users as u

In: 在:

SELECT
    u.id,
    u.user_name,
    COALESCE(m1.longitude, 0) as longitude,
    COALESCE(m1.latitude, 0) as latitude
FROM users u
LEFT JOIN map m1 ON m1.user_id = u.id
LEFT JOIN map m2 ON m2.user_id = m1.user_id AND m2.map_id > m1.map_id
WHERE m2.map_id IS NULL

I wrote a short explanation of the query structure in this answer . 在此答案中对查询结构进行了简短说明。 It's a really nice trick to learn as it is more readable, subquery-less and performance wiser. 这是一个非常好的学习技巧,因为它更具可读性,更少子查询且更明智。

I haven't looked at the IN part yet but will if the above didn't help. 我还没有看过IN部分,但是如果以上内容没有帮助,我会做的。

Edit1: You can extract the created date and use a MAX() instead. 编辑1:您可以提取创建的日期,并改用MAX()。

SELECT
    u.id,
    u.user_name,
    COALESCE(m1.longitude, 0) as longitude,
    COALESCE(m1.latitude, 0) as latitude,
    created.LatestTime
FROM (SELECT MAX(created) FROM map WHERE user_id = 1) created
INNER JOIN users u ON TRUE
LEFT JOIN map m1 ON m1.user_id = u.id
LEFT JOIN map m2 ON m2.user_id = m1.user_id AND m2.map_id > m1.map_id
WHERE m2.map_id IS NULL

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM