【问题标题】:Aggregate function in SQL WHERE-ClauseSQL WHERE 子句中的聚合函数
【发布时间】:2011-06-11 23:38:27
【问题描述】:

在大学的一次考试中有一道题;是否可以在SQL WHERE 子句中使用聚合函数。

我一直认为这是不可能的,我也找不到任何例子。但是我的回答被标记为假,现在我想知道在哪些情况下可以在WHERE 中使用聚合函数。此外,如果不可能的话,最好能得到一个链接到描述它的规范。

【问题讨论】:

    标签: sql


    【解决方案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 &lt; (SELECT MAX(id) FROM t)
    • 是的,你是对的。我只记得在我早期的数据库教程中,有可能在不使用 TOP、LIMIT 或 ROWNUM 的情况下选择前 5 行。
    • 是的,但是聚合函数在子查询的 select 子句中,而不是在 WHERE 中。而且我认为子查询不能被视为聚合函数。
    【解决方案5】:
    【解决方案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&gt;500)

      1. 内部查询用于获取需要过滤的结果。
      2. 必须为必须过滤掉的聚合函数指定一个 ALIAS 名称,因为外部查询无法访问或识别聚合函数中列的实际名称。
      3. 最后,过滤器可以应用于内部查询中列的别名

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2010-09-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-12-07
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多