简体   繁体   English

使用UNIONS优化MySQL查询

[英]Optimising a MySQL query with UNIONS

I've got a query (which works) to show the average number of replies to messages containing specific keywords. 我有一个查询(有效)以显示对包含特定关键字的邮件的平均答复数。

But I think it could be optimised - we're worried that as the database grows this query will become very slow, especially if we use a larger date range. 但是我认为它可以进行优化-我们担心随着数据库的增长,此查询将变得非常慢,尤其是当我们使用较大的日期范围时。

Here's a sample of the current query: 这是当前查询的示例:

SELECT 'text1' AS "text", ROUND(AVG (a.rt_count),2) AS "Average over 100 days"
FROM 
(SELECT COUNT(reply.id) AS rt_count
FROM message LEFT OUTER JOIN reply ON (message.id = reply.message)
WHERE message.text LIKE '%text1%'
AND message.created_date >= (CURDATE() - INTERVAL 100 DAY)
GROUP BY message.id
) AS a
UNION
SELECT 'text2' AS "text", ROUND(AVG (a.rt_count),2) AS "Average over 100 days"
FROM 
(SELECT COUNT(reply.id) AS rt_count
FROM message LEFT OUTER JOIN reply ON (message.id = reply.message)
WHERE message.text LIKE '%text2%'
AND message.created_date >= (CURDATE() - INTERVAL 100 DAY)
GROUP BY message.id
) AS a 
UNION
SELECT 'text3' AS "text", ROUND(AVG (a.rt_count),2) AS "Average over 100 days"
FROM 
(SELECT COUNT(reply.id) AS rt_count
FROM message LEFT OUTER JOIN reply ON (message.id = reply.message)
WHERE message.text LIKE '%text3%'
AND message.created_date >= (CURDATE() - INTERVAL 100 DAY)
GROUP BY message.id
) AS a 

As you can see, the only thing that really changes is the WHERE message.text LIKE '%text1%' which adds lots of redundant code. 如您所见,唯一真正改变的是WHERE message.text LIKE '%text1%' ,它添加了许多冗余代码。 Any optimisation ideas? 有什么优化想法吗? - all advice much appreciated -非常感谢所有建议

SELECT case when message.text like '%text1%'
            then 'text1'
            when message.text like '%text2%'
            then 'text2'
            when message.text like '%text3%'
            then 'text3'
       end AS "text", 
       ROUND(AVG (a.rt_count),2) AS "Average over 100 days"
FROM 
(SELECT COUNT(reply.id) AS rt_count
FROM message LEFT OUTER JOIN reply ON (message.id = reply.message)
WHERE (message.text like '%text1%'
or message.text like '%text2%'
or message.text like '%text3%')
AND message.created_date >= (CURDATE() - INTERVAL 100 DAY)
GROUP BY message.id
) AS a 

To make your query perform better, use UNION ALL instead of UNION . 为了使查询性能更好,请使用UNION ALL而不是UNION This will eliminate the unnecessary step of eliminating duplicates. 这将消除消除重复项的不必要步骤。

If one row can match at most one of the texts, then the following will work: 如果一行最多可以匹配其中一种文本,则可以使用以下内容:

SELECT MatchText AS "text", ROUND(AVG (a.rt_count),2) AS "Average over 100 days"
FROM (SELECT MatchText, m.Id, COUNT(reply.id) AS rt_count
      FROM (select m.*,
                   (case when m.text like '%text1%' then 'Text1'
                         when m.text like '%text2%' then 'Text2'
                         when m.text like '%text3%' then 'Text3'
                    end) as MatchText
            from message m
           ) m LEFT OUTER JOIN
           repl
           ON (m.id = reply.message)
      WHERE MatchText is not NULL AND
            message.created_date >= (CURDATE() - INTERVAL 100 DAY)
      group by MatchText, m.Id
     ) t
group by MatchText

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

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