简体   繁体   中英

Complicated SQL query performance issue (group by, case statement)

The sql query (at the end of the post) has serious performance issues. It takes up to 1 second on a small data set. I'm quite new to SQL. Could anyone give me some advices on how to optimize the query? I have two tables, user table and notification table.

User table:

user_id, first_name, profile_image

Notification table:

category, to_uid, from_id, title_id, create_time (linux timestamp)

I want to return aggregated notifications for a specified to_uid group by combinations of category and title_id fields. There is a category called 'special'. If the category is called 'special', then we shouldn't aggregate that row. If a row's category is 'special', it's from_id and title_id fields are always NULL.

Notification sample data:

category, to_uid,   from_id, title_id, create_time (linux timestamp)
like_post, 4,          3,       5,       123456
follow,    4,          3,       4,       123457
like_post, 4,          5,       5,       123478
special,   4,          NULL,    NULL,    123467 
special,   4,          NULL,    NULL,    123468 

Expected result:

category,  to_uid,  from_id,   title_id,     first_name_list
like_post,   4,        3,5          5,         uid_3_first_name,uid_5_first_name 
follow,      4,        3,           4,         uid_3_first_name
special,     4,        NULL,        NULL,      NULL
special,     4,        NULL,        NULL,      123468 

SELECT n.category, n.to_uid, n.title_id, n.title, n.create_time, 
    CASE WHEN n.category <> "category1"
        THEN GROUP_CONCAT(u.first_name)
    END user_name_list,
    GROUP_CONCAT(n.from_id) from_id_list, GROUP_CONCAT(u.profile_image) profile_image_list,
    CASE WHEN n.category IN ("category2")
            THEN concat_ws("_", n.title_id, n.category)
         ELSE concat_ws("_", "uni", n.id, n.category)
    END AS group_id
FROM notification n, user u
WHERE CASE WHEN n.category <> "category1"
            THEN n.from_id = u.user_id
           ELSE 1 = 1
      END
AND to_uid = 20
GROUP BY group_id
ORDER BY n.create_time DESC
LIMIT 20;

Try to use LEFT JOIN instead

FROM notification n LEFT JOIN user u 
   ON n.category <> "category1" AND n.from_id = u.user_id
WHERE
to_uid = 20

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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