2016-09-16 60 views
0

我是SQL新手,我想知道如果我在查询中同时使用WHERE和HAVING子句,HAVING子句中的条件顺序很重要。例如,对于以下查询(从书中取出),它们是否完全一样?我的理解是HAVING被应用于GROUP数据,这些数据已经被WHERE子句过滤,然后SUM()函数将只应用于那些过滤的数据。但是,在第二个查询中,事先未应用WHERE子句,并且在HAVING子句末尾应用条件InvoiceDate BETWEEN'2016-01-01'和'2016-01-31',因此SUM()将从所有数据计算,这与第一个查询不同。我理解对吗?在SQL中的having子句中,条件的顺序是否重要?

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

回答

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

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

  1. FROM
  2. ON
  3. JOIN
  4. WHERE
  5. GROUP BY WITH CUBE或WITH ROLLUP
  6. HAVING
  7. SELECT
  8. DISTINCT
  9. ORDER BY
  10. TOP

既然现在你知道了订单,就可以找出处理将会如何。请参阅this link了解更多信息。

0

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

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