了解WHERE如何使用GROUP BY和Aggregation

时间:2012-12-22 20:22:07

标签: sql

我的查询 -

select cu.CustomerID,cu.FirstName,cu.LastName, COUNT(si.InvoiceID)as inv --1
from Customer as cu inner join SalesInvoice as si --2
on cu.CustomerID = si.CustomerID -- 3
-- put the WHERE clause here ! --4   
group by cu.CustomerID,cu.FirstName,cu.LastName -- 5
where cu.FirstName = 'mark' -- 6

输出正确的代码 -

enter image description here

我得到错误 - 关键字'where'附近的语法不正确。

你能告诉我为什么会收到这个错误吗? 我想知道为什么WHERE出现在GROUP BY之前而不是之后。

5 个答案:

答案 0 :(得分:18)

您的订单有误。 WHERE子句位于GROUP BY

之前
select cu.CustomerID,cu.FirstName,cu.LastName, COUNT(si.InvoiceID)as inv 
from Customer as cu 
inner join SalesInvoice as si 
   on cu.CustomerID = si.CustomerID 
where cu.FirstName = 'mark' 
group by cu.CustomerID,cu.FirstName,cu.LastName

如果您想在GROUP BY之后执行过滤器,那么您将使用HAVING子句:

select cu.CustomerID,cu.FirstName,cu.LastName, COUNT(si.InvoiceID)as inv 
from Customer as cu 
inner join SalesInvoice as si 
   on cu.CustomerID = si.CustomerID 
group by cu.CustomerID,cu.FirstName,cu.LastName
having cu.FirstName = 'mark' 

HAVING子句通常用于聚合函数过滤,因此在GROUP BY

之后应用它是有意义的

要了解此处的操作顺序,请article explaining the order。从文章中,SQL中的操作顺序是:

  

首先,我认为查找执行SQL指令的顺序会很好,因为这将改变我可以优化的方式:

FROM clause
WHERE clause
GROUP BY clause
HAVING clause
SELECT clause
ORDER BY clause

使用此订单,您将在WHERE之前的GROUP BY中应用过滤器。 WHERE用于限制记录数。

以这种方式思考,如果您之后应用WHERE,那么您将返回更多记录,然后您想要分组。首先应用它,减少记录集然后应用分组。

答案 1 :(得分:3)

where子句位于group by之前,因为从概念上讲,您在分组之前进行过滤,而不是之后。您希望将分组的输出限制为仅匹配的输出,而不是对由于过滤器而可能会丢弃的项目执行分组。

答案 2 :(得分:2)

SQL允许您过滤GROUP BY的结果 - 它被称为HAVING子句。

如果你想过滤在分组之前可以确定的东西(即每个人都有FirstName ='Mark'),那就是通过WHERE完成的。

但是,如果你想过滤每个有4张或更多发票的人(比如做COUNT之后你就不会知道的话),那么你就可以使用HAVING了。

答案 3 :(得分:2)

WHERE之前使用GROUP BY子句,因为它更有意义。在分组之前使用WHERE子句中指定的过滤器。分组后,您可以使用HAVING子句,类似于WHERE,但您也可以按聚合值进行过滤。

比较

-- Select the number of invoices per customer (for Customer 1 only)
SELECT
  si.CustomerID,
  COUNT(*) as InvoiceCount
FROM
  SalesInvoice as si   
WHERE
  si.CustomerID = 1
  -- You cannot filter by count(*) here, because grouping hasn't taken place yet.
GROUP BY 
  si.CustomerID -- (Not needed in this case, because of only 1 customer) 

针对

-- Select all invoices of customers that have more than three invoices
SELECT
  si.CustomerID,
  COUNT(*) as InvoiceCount
FROM
  SalesInvoice as si   
GROUP BY
  si.CustomerId
HAVING
  -- You can filter by aggregates, like count, here.
  COUNT(*) > 3

答案 4 :(得分:1)

假设您的数据库中有100,000人。其中9人被命名为马克。为什么数据库应该对所有100,000进行Count操作,然后抛出99,991 NOT not named Mark?首先过滤掉Marks似乎更聪明,然后只计数9次?使操作更快。