18

我的查询 -

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

输出正确的代码 -

在此处输入图像描述

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

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

4

5 回答 5

43

你的顺序错了。该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

要了解此处的操作顺序,请参阅解释顺序的文章。从文章中SQL中的操作顺序是:

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

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

使用此顺序,您将WHEREGROUP BY. WHERE用于限制记录数 。

这样想,如果你应用WHEREafter 然后你会返回更多的记录然后你会想要分组。首先应用它,减少记录集,然后应用分组。

于 2012-12-22T20:23:47.193 回答
5

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

于 2012-12-22T20:27:48.080 回答
3

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

如果您想过滤可以在分组之前确定的内容(即 FirstName = 'Mark' 的每个人),可以通过 WHERE 完成。

但是,如果您想过滤拥有 4 个或更多发票的每个人(即,在执行 COUNT之后您才知道的东西),那么您可以使用 HAVING。

于 2012-12-22T20:27:36.697 回答
3

WHERE子句用于 before 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
于 2012-12-22T20:29:47.387 回答
1

Let's say you have 100,000 people in your database. 9 of whom are named Mark. Why should the database do a Count operation on all 100,000, then throw out the 99,991 NOT named Mark? Doesn't it seem smarter to filter out the Marks first, then do the Count only 9 times? Makes the operation a whole lot faster.

于 2012-12-22T20:55:19.277 回答