SQL WHERE-Clause中的聚合函数


76

在大学考试中有一个问题。是否可以在SQL WHERE子句中。

我一直以为这是不可能的,我也找不到任何可能的例子。但是我的答案被标记为“错误”,现在我想知道在哪种情况下可以在中使用聚合函数WHERE。同样,如果不可能的话,最好在描述的地方链接到规范。

Answers:


32

您还没有提到DBMS。假设您正在使用MS SQL Server,我发现了一条不言自明的T-SQL错误消息:

“除非聚集在HAVING子句或选择列表中包含的子查询中,否则聚集可能不会出现在WHERE子句中,并且正在聚集的列是外部引用”

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 ;

1
是的,我没有提到DBMS,因为未指定任何DBMS。它只是说SQL -_-
n3,2011年

1
我认为这种可能性是在SQL-92规范中添加的。各种产品何时添加功能都不知道。仅使用MySQL和SQL-Server进行测试显示出明显不同的行为(SQL-Server更严格,可能更接近规范)。如果其他人可以检查其他SQL实现,那将很有趣。
ypercubeᵀᴹ

尽管纯粹主义者会不同意,但我工作过的大多数地方都说SQL表示使用TSQL的Microsoft SSMS
JosephDoggie

111

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)

3
是的,有可能我知道。但是这里给出了。我认为这是一个定义。
2011年

1
谢谢!正是我需要知道和理解的。投票。
卢卡斯

1
谢谢,我要把查询留在作业中,然后我找到这个...您的回答确实对我有帮助
正如Bhullar

1
谢谢,这节省了我很多时间,所有其他来源都没有提供您所做的简便性。完美的答案。
杰夫

13

您不能在WHERE子句中直接使用聚合;这就是HAVING子句的作用。

您可以使用在WHERE子句中包含汇总的子查询。


1
我知道有可能作为子查询,但是我不确定是否可以说我可以在WHERE中使用聚合函数...我认为这是一个定义。
2011年

1
@ n3on:我同意...我认为不能在WHERE子句中直接使用聚合-正如我所说。只能将它们用作子查询的一部分-在我的书中,这不会算作“在WHERE子句中”。如果您给出了一个细微而细微的答案,我看不出他们会给您带来什么麻烦。如果这是一个多项选择题,那么您几乎会陷入困境。
乔纳森·勒夫勒

2
参见蒂姆的答案。有可能的。
ypercubeᵀᴹ

11

更新查询:

select id from t where id < (select max(id) from t);

它将选择表t中除最后一行以外的所有内容。


2
我相信这将取决于Tim提到的DBMS。在标准SQL中,您必须将其编写为SELECT id FROM t WHERE id < (SELECT MAX(id) FROM t)
Coding District

1
是啊,你说得对。我只是记得,在我的早期数据库教程中,有可能需要我们选择前5行而不使用TOP或LIMIT或ROWNUM。
Chandranshu

2
是的,但是聚合函数位于子查询的select子句中,而不位于WHERE中。而且我认为子查询不能被视为聚合函数。
2011年


3

另一个解决方案是将聚合函数移至标量用户定义函数

创建您的功能:

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。

希望可以帮助某人。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.