使用 GROUP BY/HAVING 重构子查询?

Posted

技术标签:

【中文标题】使用 GROUP BY/HAVING 重构子查询?【英文标题】:Refactor subqueries using GROUP BY/HAVING? 【发布时间】:2009-02-04 15:36:17 【问题描述】:

我正在构建一个 mysql 查询,以确定在给定日期范围内出现的多个类别中的每个类别有多少项目。我最初的尝试是这样的:

select Title, 
  (select count(*) from entries where CategoryID=1
    and Date >= @StartDate and Date <= @EndDate) as Cat1,
  (select count(*) from entries where CategoryID=2
   and Date >= @StartDate and Date <= @EndDate) as Cat2,
  (select count(*) from entries where CategoryID is null
   and Date >= @StartDate and Date <= @EndDate) as UnkownCategory
from entries
  where Date >= @StartDate and Date <= @EndDate

该表非常大,我想重构查询以加快速度,但我不确定如何使用 GROUP BY/HAVING 语句重写它,或者我是否还缺少其他方法?

编辑:示例结果集 - 类似这样:

Title | Category 1 Total | Category 2 Total | Unknown Category Total
ABC     1                  3                  0
DEF     2                  7                  2

【问题讨论】:

你能提供一个示例结果集吗? 【参考方案1】:
select Title, SUM(CategoryID=1) as Cat1, SUM(categoryID=2) as Cat2,
SUM(categoryID IS NULL) as UnknownCategory
FROM entries
WHERE Date BETWEEN @StartDate AND @EndDate
GROUP BY Title

你可以在 sum() 函数中粘贴表达式:真值等于 1,假值等于 0。我还使用了 BETWEEN 运算符,它的速度要快一些。

一种会返回不同结果布局但概念上更简单的替代方案:

select Title, CategoryID, count(*)
from entries
WHERE Date BETWEEN @StartDate AND @EndDate
group by Title, CategoryID

【讨论】:

感谢此格式完美,无需更改报告生成。它似乎也很快。 是的,第二种解决方案是 rikh 建议的。我坚持使用 SUM 版本,只要它足够快,因为它的格式更容易处理。谢谢!【参考方案2】:

如何按类别 id 分组,然后使用 have 语句过滤掉特定类别,例如:

select CategoryID, count(*) 
from entries 
where Date >= @StartDate AND Date <= @EndDate
group by CategoryID
having CategoryID = 1 or CategoryID = 2 or CategoryID is null

如果每个类别有多个标题,您可以按两个字段分组:

select Title, CategoryID, count(*) 
from entries 
where Date >= @StartDate AND Date <= @EndDate
group by Title, CategoryID
having CategoryID = 1 or CategoryID = 2 or CategoryID is null

【讨论】:

将 categoryID 条件放在 where 子句中,而不是 having 子句中。【参考方案3】:
Select COUNT(*), sTitle, CategoryID FROM entries 
WHERE Date >= @StartDate and Date <= @EndDate 
GROUP BY CategoryID, sTitle

【讨论】:

最好将 CategoryID 添加到结果集中! 谢谢!我实际上需要每个条目的计数,但我认为稍微修改一下就可以了: Select count(*), sTitle, CategoryID FROM entries where Date >= @StartDate and Date

以上是关于使用 GROUP BY/HAVING 重构子查询?的主要内容,如果未能解决你的问题,请参考以下文章

使用 GROUP BY ... HAVING 优化 MySQL 查询时遇到问题

MySQL进阶5--分组排序和分组查询 group by(having) /order by

SQL -- WHERE、GROUP BY、HAVING 查询

SQL重复记录查询-count与group by having结合查询重复记录

查询语句中select from where group by having order by的执行顺序

使用 GROUP_CONCAT、GROUP BY、HAVING 进行选择