【问题标题】:Having and Where in combination with Group By拥有和在哪里与 Group By 结合
【发布时间】:2022-01-08 08:36:00
【问题描述】:

当我使用GROUP BY 而不是WHERE 子句时,我学会了使用HAVING,并且从未遇到任何问题。今天我在 w3schools.com 的一个 SQL 学习页面上看到了这个:

SELECT Employees.LastName, COUNT(Orders.OrderID) AS NumberOfOrders
FROM Orders
INNER JOIN Employees ON Orders.EmployeeID = Employees.EmployeeID
WHERE LastName = 'Davolio' OR LastName = 'Fuller'
GROUP BY LastName
HAVING COUNT(Orders.OrderID) > 25;
  1. 为什么这应该有效?
  2. 什么时候应该使用这个?

【问题讨论】:

  • “当我使用GROUP BY 而不是WHERE 子句时,我学会了使用HAVING 你学错了。 WHERE 始终是允许的。 HAVING 用于根据聚合函数过滤结果,例如查询中的 COUNT,它不会替换 WHEREWHERE 是迄今为止不使用聚合函数的子句更合适的位置(再次,如上所示)。
  • 我不能写 HAVING COUNT(Orders.OrderID) > 25 和 (LastName = 'Davolio' OR LastName = 'Fuller') 给我同样的结果。在这种情况下哪里是多余的
  • 可以,但不建议这样做。我怀疑这样的查询也会降低性能,因为 RDBMS 会聚合 LastNameall 值然后过滤,而不是过滤然后聚合。这意味着需要进行表扫描(我没有对此进行测试,但HAVING is processed after the GROUP BY 所以这似乎是合乎逻辑的)。
  • 可能优化器正在重写您的查询以隐式使用离散值谓词作为实际的WHERE 并帮助您摆脱困境。正如@Larnu(正确)指出的那样,您可以做很多您可能不应该做的事情。知道如何区分差异,而不是仅仅“因为它有效”而继续前进,这对你很有帮助。
  • 看看一个 very 简单的查询,是的,优化器似乎是(正如@paneerakbari 所说)“拯救你”,它有效地传播了该子句LastName IN ('Davolio','Fuller')WHERE 而不是 HAVING,因为它执行查找并期望 18 行,但我怀疑在更复杂的查询中,您可能不会那么幸运。 db<>fiddle

标签: sql sql-server tsql


【解决方案1】:

WHEREHAVING 之间的区别是您何时应该使用一个与另一个,甚至两者结合使用的核心。

HAVING 使您能够根据聚合值来归档结果集。在您的示例中,您将查询返回的数据限制为仅聚合 (COUNT) 大于 25 的那些行。由于语法限制,无法在 WHERE 中定义此类谓词。

WHERE 关键字用于为基于离散(非聚合)值的查询定义谓词。在您的示例中,WHERE 根据 LastName 和 FirstName 值限制结果。

它们可以作为有效的语法相互结合使用,因为它们执行不同的(尽管非常相似)操作,而这些操作不能由另一个单独完成。至于为什么要使用它,只是需要根据聚合条件和离散条件来限制结果集。

【讨论】:

    猜你喜欢
    • 2011-02-23
    • 1970-01-01
    • 1970-01-01
    • 2012-03-04
    • 1970-01-01
    • 1970-01-01
    • 2021-12-10
    • 2016-11-15
    相关资源
    最近更新 更多