在连接中使用 Where 子句,以及 Group by 和 Order By
Posted
技术标签:
【中文标题】在连接中使用 Where 子句,以及 Group by 和 Order By【英文标题】:Using Where clause in a join, with Group by and Order By 【发布时间】:2012-05-12 02:16:20 【问题描述】:我正在使用 mysql 经典模型数据库。以下查询工作正常(注意 where 子句)
select
customers.customerNumber as 'Customer ID',
customers.customerName as 'Customer Name',
count(orders.orderNumber) as 'Total Orders Placed'
from customers
left join orders on customers.customerNumber = orders.customerNumber
where customers.customerNumber > 200
group by
customers.customerNumber
order by
3 asc
但以下导致错误。目的是仅显示结果行集中那些下达 3 个以上订单的客户。我做错了什么?
select
customers.customerNumber as 'Customer ID',
customers.customerName as 'Customer Name',
count(orders.orderNumber) as 'Total Orders Placed'
from customers
left join orders on customers.customerNumber = orders.customerNumber
where count(orders.orderNumber) > 3
group by
customers.customerNumber
order by
3 asc
MySQL 错误为:错误代码:1111. 组函数使用无效
【问题讨论】:
【参考方案1】:聚合函数(COUNT(), AVG(), SUM(),
等)不能出现在 WHERE
子句中,因为它们的计算时间。相反,它们属于HAVING
子句:
select
customers.customerNumber as 'Customer ID',
customers.customerName as 'Customer Name',
count(orders.orderNumber) as 'Total Orders Placed'
from customers
left join orders on customers.customerNumber = orders.customerNumber
group by
customers.customerNumber
HAVING count(orders.orderNumber) > 3
order by
3 asc
【讨论】:
而且由于我们希望客户有超过 3 个订单,因此将left join
转为 inner join
没有任何害处【参考方案2】:
更有效的方法是通过聚合将组移动到嵌套派生表中并加入该表。
SELECT
c.customerNumber AS 'Customer ID',
c.customerName AS 'Customer Name',
o.orderCount AS 'Total Orders Placed'
FROM
customers c
LEFT JOIN
(SELECT
customerNumber,
COUNT(*) AS orderCount
FROM
orders
GROUP BY
customerNumber) o
ON
c.customerNumber = o.customerNumber
WHERE
o.orderCount > 3
ORDER BY
3
【讨论】:
效率更高或更低(或者它是否无关紧要,优化器会在内部找出一个查询并将其转换为另一个)取决于优化器。【参考方案3】:在where子句中有一种间接使用聚合函数的方法
您可以将查询重写为
select customers.customerNumber as 'Customer ID',
customers.customerName as 'Customer Name',
count(orders.orderNumber) as 'Total Orders Placed'
from customers left join orders on customers.customerNumber =
orders.customerNumber
where
(SELECT CASE
WHEN count(orders.orderNumber) > 3 THEN
'TRUE'
ELSE
'FALSE'
END
FROM DUAL) = 'TRUE'
group by customers.customerNumber
order by 3 asc
这里在 select 子句中使用 count 函数,根据 count 计算返回 FALSE 字符串的 TRUE。
希望对你有帮助
【讨论】:
【参考方案4】:请试试这个
select
customers.customerNumber as 'Customer ID',
customers.customerName as 'Customer Name',
count(orders.orderNumber) as 'Total Orders Placed'
from customers
inner join orders on customers.customerNumber = orders.customerNumber
group by
customers.customerNumber,
customers.customerName
having count(orders.orderNumber) > 3
order by
3 asc
【讨论】:
【参考方案5】:这是您要实现的目标的简化版本。
SELECT
customers.customerName,
COUNT(orders.orderNumber) totalOrders
FROM
customers
JOIN
orders ON customers.customerNumber = orders.customerNumber
GROUP BY customers.customerName
HAVING totalOrders > 2;
【讨论】:
以上是关于在连接中使用 Where 子句,以及 Group by 和 Order By的主要内容,如果未能解决你的问题,请参考以下文章
不能在 Group by/Order by/Where/ON 子句中使用 Group 或 Aggregate 函数(min()、max()、sum()、count()、...等)