2010-06-20 138 views
2

我試圖理解使用JOINCOUNT(*)GROUP BY進行非常簡單的查詢的正確方法。我實際上已經開始工作了(見下文),但從我讀過的內容來看,我正在使用額外的GROUP BY,我不應該這樣做。在GROUP BY和COUNT之後加入另一個表

(注:下面的問題是不是我的實際問題(其中用更復雜的表交易),但我試圖拿出一個類似的問題)

我有兩個表:

Table: Person 
------------- 
key name  cityKey 
1 Alice 1 
2 Bob  2 
3 Charles 2 
4 David 1 

Table: City 
------------- 
key name 
1 Albany 
2 Berkeley 
3 Chico 

我想要做的人查詢(有一些WHERE條款)返回

  • 匹配的人在每個城市的數量
  • 城市的關鍵
  • 城市的名稱。

如果我不

SELECT COUNT(Person.key) AS count, City.key AS cityKey, City.name AS cityName 
FROM Person 
LEFT JOIN City ON Person.cityKey = City.key 
GROUP BY Person.cityKey, City.name 

我得到的結果,我想

count cityKey cityName 
2  1   Albany 
2  2   Berkeley 

然而,我已經read是扔在GROUP BY條款半句(City.name )只是爲了讓它工作是錯誤的。

那麼有什麼正確的方法來做到這一點?我一直試圖谷歌的答案,但我覺得有一些基本的東西,我只是沒有得到。

回答

1

您的查詢只適用於MySQL,因爲您在Person.cityKey上分組,但是選擇city.key。所有其他數據庫將要求您使用像min(city.key)這樣的聚合,或將City.key添加到group by子句。

由於城市名稱和市重點的組合是唯一的,下面是等價的:

select count(person.key), min(city.key), min(city.name) 
... 
group by person.citykey 

或者:

select count(person.key), city.key, city.name 
... 
group by person.citykey, city.key, city.name 

或者:

select count(person.key), city.key, max(city.name) 
... 
group by city.key 

在所有行團隊將擁有相同的城市名稱和密碼,因此,如果您使用maxmin聚合。

P.S.如果你想只計算不同的人,即使他們有多個行,試試:

count(DISTINCT person.key) 

代替

count(person.key) 
+0

我認爲這可能是一個錯字,我相信他希望他的「group by」在他的「SELECT」條款中包含非聚合列。然而,我可能是錯的。 – Pointy 2010-06-20 16:58:10

+0

對於第二個例子,你在'group by'部分有一堆東西;從我在帖子中鏈接的頁面中,他們說這是錯誤的做法。但是,「MIN」部分起作用; (我認爲只適用於'int'類型的列) – 2010-06-20 16:59:49

+0

@Craig S:如果我讀了你正確鏈接的帖子,他們只是說你應該在你選擇的列上按'分組'。我的第二個例子正確。這篇文章還提到如果你做錯了,你會得到「惱人的錯誤」。 MySQL是唯一的數據庫,將接受「不正確」的方式沒有「煩人的錯誤」:) – Andomar 2010-06-20 17:03:33

3

我不認爲這是在這種情況下,「錯誤」,因爲你在城市名稱和城市關鍵字之間有一對一的關係。你可以重寫它,這樣你就可以加入一個子選擇,以按鍵重新計算人到城市的數量,再次向城市名稱查詢名稱,但是有爭議的是,這樣會更好。我猜想這是一個風格和觀點問題。

select PC.ct, City.key, City.name 
    from City 
    join (select count(Person.key) ct, cityKey key from Person group by cityKey) PC 
    on City.key = PC.key 

如果我的SQL是不是太生疏:-)

+0

http://stackoverflow.com/questions/23278277/select-all-columns-from-table-1-and-one-列從表二 - 這-IS-分組-b/23278417?noredirect = 1#comment35632889_23278417幫助 – TommyT 2014-04-24 22:19:39

0

不過,我讀過,扔在 該組的最後一部分BY子句 (City.name)剛使其工作是 錯誤。

這沒有錯。您必須瞭解查詢優化器如何查看您的查詢。它被解析的順序是要求你「拋出最後一部分」。優化看到您的查詢在一個類似於這樣的順序:

  • 所需的表的連接
  • 複合數據集是通過在WHERE子句
  • 剩餘行切碎過濾成組由GROUP BY子句,然後通過SELECT/ORDER BY,UPDATE或DELETE通過HAVING子句
  • 再次過濾它們。

這裏的要點是,並不是GROUP BY必須命名SELECT中的所有列,但事實上卻是相反的 - SELECT不能包含任何不在GROUP BY中的列。

+1

除了MySQL :) – Andomar 2010-06-20 17:04:13

+0

使用聚合函數比向組添加內容更好嗎? – 2010-06-20 17:05:24

+0

@Andomar非常真實,但我認爲我們一般在這裏談論SQL;) – ahsteele 2010-06-20 17:08:12

3

...我讀過,扔在GROUP BY子句(City.name)的最後部分只是爲了使它的工作是錯誤的。

你誤會了,你把它弄倒了。
標準SQL 需要您在GROUP BY指定沒有被包裹在聚合函數的SELECT中提到的所有列。如果您不希望GROUP BY中的某些列,則將它們包含在聚合函數中。根據數據庫的不同,您可以使用分析/窗口功能OVER ...

但是,MySQL和SQLite提供了「功能」,您可以從組中忽略這些列 - 這會導致無法結束「爲什麼這個端口不是從MySQL到fill_in_the_blank數據庫?!「 Stackoverflow和衆多其他網站&論壇。

+0

與Andomar建議的使用'Min(city.name)'相比,爲'Group By'增加'City.name''更好'(即更快,更便攜等)? – 2010-06-20 17:03:54

+0

@克雷格S:取決於你的需求。但是爲了不必在GROUP BY中使用聚合函數是有風險的 - 它需要更多的測試來確保事情是正確的。我沒有看到僅僅爲了不必在GROUP BY中定義它而使用聚合的觀點。 – 2010-06-20 17:08:19

+0

好的;我想在閱讀那篇文章後,我擔心我只是「爲了讓它工作而添加小組」,並且在這樣做時我犯了一個很大的SQL錯誤。我正在一個相對龐大的數據庫上進行操作(如果是我的例子中的表格,將會有數百萬人和數百個城市) – 2010-06-20 17:13:24