我正在尝试理解使用JOIN
,COUNT(*)
和GROUP BY
进行非常简单的查询的正确方法。我实际上已经开始工作(见下文),但从我读过的内容来看,我正在使用额外的GROUP BY
我不应该这样做。
(注意:下面的问题不是我的实际问题(处理更复杂的表),但我试图提出类似的问题)
我有两张桌子:
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
)的最后一部分只是为了让它工作是错误的。
那么正确的方法是什么?我一直试图谷歌寻求答案,但我觉得有一些基本的东西,我只是没有得到。
答案 0 :(得分: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不太生锈: - )
答案 1 :(得分:3)
...我已经读过,抛出GROUP BY子句(City.name)的最后一部分只是为了让它工作是错误的。
你误解了,你倒退了。
标准SQL 要求 您在GROUP BY中指定SELECT中提到的所有未包含在聚合函数中的列。如果您不想要GROUP BY中的某些列,请将它们包装在聚合函数中。根据数据库的不同,您可以使用分析/窗口函数OVER
...
然而,MySQL和SQLite提供了“功能”,您可以在其中省略这些列中的列 - 这导致“为什么这个端口不能从MySQL填充到fill_in_the_blank数据库?!” Stackoverflow和许多其他网站&论坛。
答案 2 :(得分: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
组中的所有行都具有相同的城市名称和密钥,因此如果您使用max
或min
汇总无关紧要。
P.S。如果您只想计算不同的人,即使他们有多行,请尝试:
count(DISTINCT person.key)
而不是
count(person.key)
答案 3 :(得分:1)
然而,我已经读到了投掷 GROUP BY子句的最后一部分 (City.name)只是为了让它发挥作用 错。
没错。您必须了解查询优化程序如何查看您的查询。解析它的顺序是要求你“抛弃最后一部分”的原因。优化程序会以类似于此顺序的方式查看您的查询:
这里的要点是,GROUP BY不必命名SELECT中的所有列,但实际上它是相反的 - SELECT不能包含GROUP BY中尚未包含的任何列。