我是SQL的新手,我想知道如果我在查询中同时使用WHERE和HAVING子句,HAVING子句中的条件顺序是否重要。例如,对于以下查询(从书中取出),它们是否完全相同?我的理解是HAVING应用于已经由WHERE子句过滤的GROUP数据,然后SUM()函数将仅应用于那些过滤的数据。但是在第二个查询中,WHERE子句未事先应用,条件InvoiceDate BETWEEN' 2016-01-01' AND' 2016-01-31'在HAVING子句的末尾应用,因此SUM()将根据与第一个查询不同的所有数据进行计算。我明白了吗?
-- First Query
SELECT
InvoiceDate,
COUNT(*) AS InvoiceQty,
SUM(InvoiceTotal) AS InvoiceSum
FROM
Invoices
WHERE
InvoiceDate BETWEEN '2016-01-01' AND '2016-01-31'
GROUP BY
InvoiceDate
HAVING
COUNT(*) > 1
AND SUM(InvoiceTotal) > 100
ORDER BY
InvoiceDate DESC;
-- Second Query
SELECT
InvoiceDate,
COUNT(*) AS InvoiceQty,
SUM(InvoiceTotal) AS InvoiceSum
FROM
Invoices
GROUP BY
InvoiceDate
HAVING
COUNT(*) > 1
AND SUM(InvoiceTotal) > 100
AND InvoiceDate BETWEEN '2016-01-01' AND '2016-01-31'
ORDER BY
InvoiceDate DESC;
答案 0 :(得分:1)
顺序在HAVING
子句中无关紧要。无论如何,大部分工作都由GROUP BY
完成。如果其中一个条款的检查成本更高(例如,由于使用了用户定义的函数),则可能会有所不同。但是,您的查询并没有这样的条件。
另一方面,HAVING
和WHERE
子句中的条件之间的差异很重要。并且,您可以将第二个查询重写为:
SELECT InvoiceDate, COUNT(*) AS InvoiceQty,
SUM(InvoiceTotal) AS InvoiceSum
FROM Invoices
WHERE InvoiceDate BETWEEN '2016-01-01' AND '2016-01-31'
GROUP BY InvoiceDate
HAVING COUNT(*) > 1 AND SUM(InvoiceTotal) > 100
ORDER BY InvoiceDate DESC;
在之前过滤 GROUP BY
通常效率更高,因为它减少了处理聚合所需的数据量。
答案 1 :(得分:1)
以下步骤显示SQL Server数据库中SELECT语句的逻辑处理顺序或绑定顺序。此顺序确定在一个步骤中定义的对象何时可用于后续步骤中的子句。
从现在您知道订单,您可以了解处理方式。有关更多信息,请参阅this link。
答案 2 :(得分:0)
你假设正确。这两个查询具有相同的结果,但第一个查询通常应该是qicker,因为正如你所说,它会立即解除不需要的数据,而不是在解除它之前对其进行所有计算。
如果数据库系统有一个好的查询优化器,它可能会注意到第二个查询中的HAVING
子句的一部分可以移动到WHERE
并可能在内部重写查询,所以你在这两种情况下,最终都会得到查询#1。但你不应该依赖它。尽可能好地编写查询,即使用查询#1。