SQL WHERE 子句中的聚合函数
Posted
技术标签:
【中文标题】SQL WHERE 子句中的聚合函数【英文标题】:Aggregate function in SQL WHERE-Clause 【发布时间】:2011-06-11 23:38:27 【问题描述】:在大学的一次考试中有一道题;是否可以在SQL WHERE
子句中使用聚合函数。
我一直认为这是不可能的,我也找不到任何例子。但是我的回答被标记为假,现在我想知道在哪些情况下可以在WHERE
中使用聚合函数。此外,如果不可能的话,最好能得到一个链接到描述它的规范。
【问题讨论】:
【参考方案1】:HAVING 类似于 WHERE 的聚合函数,或者您可以使用子查询。
select EmployeeId, sum(amount)
from Sales
group by Employee
having sum(amount) > 20000
或者
select EmployeeId, sum(amount)
from Sales
group by Employee
where EmployeeId in (
select max(EmployeeId) from Employees)
【讨论】:
是的,如果我知道的话,这是可能的。但是给出了 WHERE。我认为这是一个定义。 谢谢!正是我需要知道和理解的。赞成票。 谢谢,我打算把我的查询留在作业中,然后我找到了这个……你的回答对我很有帮助 谢谢,这为我节省了很多时间,所有其他来源都没有你所做的那样简单。完美的答案。 必须做什么[从员工中选择 max(EmployeeId)],在第二个示例中与第一个示例 [具有 sum(amount) > 20000]。【参考方案2】:您还没有提到 DBMS。假设您使用的是 MS SQL-Server,我发现了一条不言自明的 T-SQL 错误消息:
"聚合可能不会出现在 WHERE 子句除非它在一个 包含在 HAVING 子句中的子查询 或选择列表,并且该列是 聚合是外部引用"
http://www.sql-server-performance.com/
还有一个可以在子查询中使用的例子。
对于有 5 个或更多订单的客户,显示所有客户和最小订单(其他订单为 NULL):
SELECT a.lastname
, a.firstname
, ( SELECT MIN( o.amount )
FROM orders o
WHERE a.customerid = o.customerid
AND COUNT( a.customerid ) >= 5
)
AS smallestOrderAmount
FROM account a
GROUP BY a.customerid
, a.lastname
, a.firstname ;
更新。
以上在 SQL-Server 和 mysql 中运行,但它没有返回我预期的结果。下一个更接近。我想这与字段customerid
、GROUPed BY 和用于查询-子查询连接的字段在第一种情况下是外部表的PRIMARY KEY 有关,而在第二种情况下则不是。
为拥有 5 个或更多订单的客户显示所有客户 ID 和订单数量(其他订单为 NULL):
SELECT o.customerid
, ( SELECT COUNT( o.customerid )
FROM account a
WHERE a.customerid = o.customerid
AND COUNT( o.customerid ) >= 5
)
AS cnt
FROM orders o
GROUP BY o.customerid ;
【讨论】:
是的,我没有提到 DBMS,因为没有任何指定。它只是说 SQL -_- 我认为这种可能性是在 SQL-92 规范中添加的。不知道各种产品何时添加了该功能。仅使用 MySQL 和 SQL-Server 进行测试显示出略有不同的行为(SQL-Server 更严格,可能更接近规范)。如果其他人可以检查其他 SQL 实现,那将会很有趣。 虽然纯粹主义者不同意,但我工作过的大多数地方都说 SQL 表示 Microsoft SSMS,使用 TSQL @JosephDoggie 如果是 SQL ,请询问 SQL ,这是标准中定义的语言。【参考方案3】:您不能在 WHERE 子句中直接使用聚合;这就是 HAVING 子句的用途。
您可以在 WHERE 子句中使用包含聚合的子查询。
【讨论】:
我知道它可以作为子查询,但我不确定我是否可以说我可以在 WHERE 中使用聚合函数...我认为这是一个定义。 @n3on:我同意...我认为不可能直接在 WHERE 子句中使用聚合 - 正如我所说。只能将它们用作子查询的一部分 - 在我的书中,这不会算作“在 WHERE 子句中”。如果你给出谨慎的、细致入微的答案,我看不出他们怎么能责怪你。如果这是一个多选题,那你就更接近卡住了。 见蒂姆的回答。这是可能的。【参考方案4】:更新的查询:
select id from t where id < (select max(id) from t);
它将从表 t 中选择除最后一行之外的所有内容。
【讨论】:
我相信这将取决于 Tim 提到的 DBMS。在标准 SQL 中,您必须将其写为SELECT id FROM t WHERE id < (SELECT MAX(id) FROM t)
是的,你是对的。我只记得在我早期的数据库教程中,有可能在不使用 TOP、LIMIT 或 ROWNUM 的情况下选择前 5 行。
是的,但是聚合函数在子查询的 select 子句中,而不是在 WHERE 中。而且我认为子查询不能被视为聚合函数。【参考方案5】:
SELECT COUNT( * )
FROM agents
HAVING COUNT(*)>3;
查看更多链接:
http://www.w3resource.com/sql/aggregate-functions/count-having.php#sthash.90csRM4I.dpuf]
http://www.w3resource.com/sql/aggregate-functions/count-having.php
【讨论】:
【参考方案6】:另一个解决方案是将聚合函数移动到标量用户定义函数
创建你的函数:
CREATE FUNCTION getTotalSalesByProduct(@ProductName VARCHAR(500))
RETURNS INT
AS
BEGIN
DECLARE @TotalAmount INT
SET @TotalAmount = (select SUM(SaleAmount) FROM Sales where Product=@ProductName)
RETURN @TotalAmount
END
在 Where 子句中使用函数
SELECT ProductName, SUM(SaleAmount) AS TotalSales
FROM Sales
WHERE dbo.getTotalSalesByProduct(ProductName) > 1000
GROUP BY Product
参考资料:
1. 2.
希望能帮助别人。
【讨论】:
【参考方案7】:如果您在 where 子句中使用聚合函数,则意味着您希望根据该聚合函数过滤数据。就我而言,它是SUM()
。我会跳到解决方案。
(select * from(select sum(appqty)summ,oprcod from pckwrk_view group by oprcod)AS asd where summ>500)
-
内部查询用于获取需要过滤的结果。
必须为必须过滤掉的聚合函数指定一个 ALIAS 名称,因为外部查询无法访问或识别聚合函数中列的实际名称。
最后,过滤器可以应用于内部查询中列的别名
【讨论】:
以上是关于SQL WHERE 子句中的聚合函数的主要内容,如果未能解决你的问题,请参考以下文章
SQL中的WHERE子句中为啥不允许应用聚集函数呢?请通俗的解释一下或者谈谈自己的见解!