如何在 WHERE 子句中优化使用 COALESCE()?

Posted

技术标签:

【中文标题】如何在 WHERE 子句中优化使用 COALESCE()?【英文标题】:How can I use COALESCE() in WHERE clause optimally? 【发布时间】:2018-06-16 13:48:18 【问题描述】:

这是我的查询:

select coalesce(qa2.subject, qa.subject) as question_subject,
       qa.body,
       (select count(*)
        from viewed_items vi
        where coalesce(qa.related, qa.id) = vi.question_id
       ) as total_question_viewed
from questions_and_answers qa
left join questions_and_answers qa2 on qa.related = qa.id 
where body like ':entry';

如您所知,mysql 优化器永远无法在 coalesce(qa.related, qa.id) = vi.question_id 上使用索引。那么知道如何才能更优化地编写此查询吗?

【问题讨论】:

试一试where vi.question_id in(qa.related, qa.id),确保检查两个查询的解释计划 【参考方案1】:

您可以使用两个单独的子查询进行计算:

select coalesce(qa2.subject, qa.subject) as question_subject,
       qa.body,
       ( (select count(*)
          from viewed_items vi
          where qa.related = vi.question_id
         ) +
         (select count(*)
          from viewed_items vi
          where qa.related is null and qa.id = vi.question_id
         )
        ) as total_question_viewed
from questions_and_answers qa left join
     questions_and_answers qa2
     on qa.related = qa.id 
where body like ':entry';

索引可用于每个子查询,因此总体上应该更快。顺便说一句,您不必担心NULL 的值,因为相关子查询中的COUNT(*) 总是返回一个值。如果没有匹配项,则值为0

【讨论】:

您的问题完全正确。谢谢,点个赞。应该注意的是,我不能像where vi.question_id in(qa.related, qa.id) 那样使用IN 子句。因为和where coalesce(qa.related, qa.id) = vi.question_id不一样。 还有@Gordon,请看一下this question .. 我想只有你才能为它写一个性感的答案。 @Martin AJ 是的,你实际上可以使用where vi.question_id in(qa.related, qa.id) 如果它有帮助的话——但不是唯一的,因为你是对的,它不等同......所以你需要使用@987654330 @。优化器是生产惰性的专家,如果可能,它将使用索引解析第一个谓词,然后使用第二个进行过滤。这是可行的,因为一个是另一个的超集。

以上是关于如何在 WHERE 子句中优化使用 COALESCE()?的主要内容,如果未能解决你的问题,请参考以下文章

如何在where子句中使用max优化Oracle中的查询

Mysql在where子句中优化子查询

如何从 Joomla 的组件菜单项中获取 MySQL 查询结果并使用 foreach where 子句进行优化?

MySQL where 子句是线性的。如何优化

SQL语句优化方式

如何优化SQL语句