问题描述
这是我的查询,仅当在分组依据之前的WHERE中使用限制性条件时才正确运行,而在分组依据之后的Haveing中使用限制性条件时才正确运行。我认为,Haveing的行为类似于Where子句,应在需要执行Group By时使用,但是下面的查询不遵循该逻辑:
/ *计算所有项目的实际总成本,这些成本不会对任何经理造成超支。显示经理的姓名,项目和各自项目的总和。
Select mg_name,p_name,sum(actual_cost),sum(expected_cost)
From Project join manager on p_manager = mg_number
Where actual_cost <= expected_cost
Group by mg_name;
下面的错误查询会在MysqL中产生错误,指出在 (错误代码:1054。“具有子句”中的未知列“ actual_cost”)
Select mg_name,sum(expected_cost)
From Project join manager on p_manager = mg_number
Group by mg_name
Having actual_cost <= expected_cost;
解决方法
db.collection.aggregate([
{
"$project": {
/* Summing goals in the Seasons list */
"seasons_goals": {
"$sum": [
"$Seasons.goals"
]
},/* Counting the number of seasons: length of Seasons + 2 */
"nb_seasons": {
"$sum": [
{
"$size": "$Seasons"
},2
]
},/* Summing goals of the two last seasons */
"total": {
"$sum": [
"$Last_season.goals","$Last_season_2.goals"
]
}
}
},/* Calculate the average by dividing seasons_goals+total by nb_seasons */
{
"$project": {
"result": {
"$divide": [
{
"$sum": [
"$seasons_goals","$total"
]
},"$nb_seasons"
]
}
}
}
])
适用于where
之前的选定行(因此,总和将不包括选定的行)。 group by
应用于having
之后 的选定字段。它可以使用所选字段中的别名,也可以使用包含sum的表达式,因此您可以这样做:
group by
或
select mg_name,p_name,sum(actual_cost),sum(expected_cost)
from project join manager on p_manager=mg_number
group by mg_name
having sum(actual_cost) <= sum(expected_cost)
您可以考虑在以下情况下使用子查询的简称:
select mg_name,sum(actual_cost) manager_total_actual_cost,sum(expected_cost) manager_total_expected_cost
from project join manager on p_manager=mg_number
group by mg_name
having manager_total_actual_cost <= manager_total_expected_cost
,
您可以将HAVING与聚合函数一起使用。
基本上:
- 具有类似于WHERE的功能,但对GROUP BY返回的分组记录进行操作。
- HAVING适用于汇总的组记录,而WHERE适用于单个记录。
- 仅返回符合HAVING条件的组。
- HAVING要求存在GROUP BY子句。
- WHERE和HAVING可以在同一查询中使用。
例如: SELECT COUNT(Id),国家 来自客户 国家“美国” 按国家分组 拥有COUNT(Id)> = 9 按COUNT(Id)DESC排序
您可以在此dofactory article
中找到有关它的很好的参考。使用w3schools可以看到另一个很好的例子:
选择客户ID,从订单中计数(订单ID) 按客户ID分组 计数(orderid)> 1;
如果在WHERE之后尝试使用任何聚合函数,则会出现错误。 概括地说,聚合函数将在SELECT之后和HAVING之后工作,而不会在WHERE之后工作。