2012-12-22 82 views
4

我查詢的工作 -瞭解如何使用WHERE GROUP BY和聚合

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在GROUP BY之前而不是之後。

+0

羽絨選民!謹慎解釋爲什麼你投下了票? –

+0

感謝所有的好答案。很難選擇其中之一。但是,我必須選擇一個。 –

回答

13

你有順序不對。該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 

使用此命令將應用過濾器之前的GROUP BYWHEREWHERE用於限制記錄的數量。

認爲它這樣,如果你是,那麼你將返回更多的記錄之後施加WHERE那麼你將要在組。先應用它,減少記錄集然後應用分組。

+0

是的,我知道這一點。我在問題本身中提到過。我想知道爲什麼WHERE在GROUP BY之前而不是之後。 –

+0

@davidblaine看到我的編輯,包括一篇關於sql操作順序的文章 - http://www.bennadel.com/blog/70-SQL-Query-Order-of-Operations.htm – Taryn

2

SQL確實允許您在GROUP BY的結果中過濾 - 這就是所謂的HAVING子句。

如果你想要的東西,可以先於分組確定(有名字=「標記」,即每個人)過濾器,這是通過WHERE完成。然而,如果你想過濾所有擁有4張或更多發票的所有人(即,在之後做COUNT之前你不知道的東西),那麼你使用HAVING。

+0

與我的問題沒有直接關係,但很好的提示。我換了一個有和它有效的地方。謝謝。 –

+0

我想知道爲什麼HAVING可以做我想做的事,但是無法做到。奇怪 –

+0

你想要什麼?只能對名爲Mark的人進行過濾?在哪裏絕對可以做到這一點。 – ExactaBox

3

where子句出現在group by之前,因爲從概念上講,您在組之前篩選,而不是之後。您希望限制分組的輸出僅限於那些匹配的輸出,而不是對可能由於過濾器而丟棄的項目執行分組。

+0

好吧,我想我明白了。考慮一種情況 - 貴公司僱用1000名程序員。程序員可以是初級,中級,高級,領導。你只想看到領導和老年人。程序員表有很多行。但是,與你相關的行(領導者)可能只有200人(領導者和前輩)。你想按經驗分組。爲什麼要通過所有1000名程序員。取得老年人和領導。然後分組,然後獲得兩行。說得通 ? –

+0

@davidblaine正好 – tvanfosson

1

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 
1

比方說,你有10萬多人在你的數據庫。其中9人被命名爲馬克。爲什麼數據庫應該對所有100,000個進行Count操作,然後丟棄99,991 NOT命名的Mark?先把商標過濾出來看起來更聰明,然後只做9次計數?使操作更快。

+0

謝謝!!!明白了,我只是輸入了類似的東西(見tvanfosson回答評論)。請告訴我,如果這也沒關係。 –

+0

SQL不一定從上到下執行,現代DBMS中的優化器比這更聰明。性能不是問題。我認爲原因更多的是爲了人類的可讀性和一致性。 – GolezTrol

+0

也許在2012年,優化器引擎足夠聰明......我確信當SQL最初被開發時,情況並非如此。 – ExactaBox