条件的顺序在SQL中的Having子句中是否重要?

时间:2016-09-16 23:39:20

标签: sql sql-server

我是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;

3 个答案:

答案 0 :(得分:1)

顺序在HAVING子句中无关紧要。无论如何,大部分工作都由GROUP BY完成。如果其中一个条款的检查成本更高(例如,由于使用了用户定义的函数),则可能会有所不同。但是,您的查询并没有这样的条件。

另一方面,HAVINGWHERE子句中的条件之间的差异很重要。并且,您可以将第二个查询重写为:

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语句的逻辑处理顺序或绑定顺序。此顺序确定在一个步骤中定义的对象何时可用于后续步骤中的子句。

  1. FROM
  2. ON
  3. JOIN
  4. WHERE
  5. GROUP BY
  6. WITH CUBE或WITH ROLLUP
  7. HAVING
  8. 选择
  9. DISTINCT
  10. ORDER BY
  11. TOP
  12. 从现在您知道订单,您可以了解处理方式。有关更多信息,请参阅this link

答案 2 :(得分:0)

你假设正确。这两个查询具有相同的结果,但第一个查询通常应该是qicker,因为正如你所说,它会立即解除不需要的数据,而不是在解除它之前对其进行所有计算。

如果数据库系统有一个好的查询优化器,它可能会注意到第二个查询中的HAVING子句的一部分可以移动到WHERE并可能在内部重写查询,所以你在这两种情况下,最终都会得到查询#1。但你不应该依赖它。尽可能好地编写查询,即使用查询#1。