【问题标题】:Does the order of condition matter in Having clause in SQL?SQL中Having子句的条件顺序是否重要?
【发布时间】:2016-09-16 23:39:19
【问题描述】:

我是 SQL 新手,我想知道如果我在查询中同时使用 WHERE 和 HAVING 子句,HAVING 子句中的条件顺序是否重要。例如,对于以下查询(从书中取出),它们是否完全相同?我的理解是 HAVING 应用于已经被 WHERE 子句过滤的 GROUP 数据,然后 SUM() 函数将只应用于那些过滤后的数据。但是在第二个查询中,没有预先应用 WHERE 子句,并且在 HAVING 子句的末尾应用了条件 InvoiceDate BETWEEN '2016-01-01' AND '2016-01-31',因此 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;

【问题讨论】:

    标签: sql sql-server


    【解决方案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 之前过滤通常更有效,因为它减少了处理聚合所需的数据量。

    【讨论】:

      【解决方案2】:

      以下步骤显示了 SQL Server 数据库中 SELECT 语句的逻辑处理顺序或绑定顺序。此顺序确定一个步骤中定义的对象何时可用于后续步骤中的子句。

      1. 来自
      2. 开启
      3. 加入
      4. 在哪里
      5. 分组依据
      6. 使用多维数据集或使用汇总
      7. 选择
      8. 不同
      9. 订购人
      10. 顶部

      既然您现在知道订单,您就可以了解处理方式。请参阅this link 了解更多信息。

      【讨论】:

        【解决方案3】:

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

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2012-07-11
          • 2011-03-10
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-03-05
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多