5

我试图理解使用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

但是,我已经读过GROUP BY将子句 ( )的最后一部分City.name仅仅为了使它起作用是错误的。

那么这样做的正确方法是什么?我一直在尝试用谷歌搜索答案,但我觉得有些基本的东西我只是没有得到。

4

4 回答 4

4

我不认为在这种情况下它是“错误的”,因为您在城市名称和城市密钥之间存在一对一的关系。您可以重写它,以便加入子选择以通过键获取城市的人数,再次到城市表以获取名称,但有争议的是这会更好。我猜这是风格和观点的问题。

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 不是太生疏:-)

于 2010-06-20T16:56:12.837 回答
3

...我已经读过将 GROUP BY 子句 (City.name) 的最后一部分扔进去只是为了让它工作是错误的。

你误会了,你把它弄反了。
标准 SQL要求您在 GROUP BY 中指定 SELECT 中提到的所有未包装在聚合函数中的列。如果您不希望 GROUP BY 中的某些列,请将它们包装在聚合函数中。根据数据库,您可以使用分析/窗口功能OVER...

但是,MySQL 和 SQLite 提供了“功能”,您可以在其中从组中省略这些列 - 这导致“为什么这个端口不从 MySQL 到 fill_in_the_blank 数据库?!”没有尽头 Stackoverflow 和许多其他网站和论坛。

于 2010-06-20T17:00:39.620 回答
2

但是,我已经读过将 GROUP BY 子句 (City.name) 的最后一部分放入只是为了使其工作是错误的。

这没有错。您必须了解查询优化器如何查看您的查询。解析它的顺序是要求您“将最后一部分放入”的原因。优化器以类似于以下顺序的方式查看您的查询:

  • 所需的表已连接
  • 复合数据集通过 WHERE 子句过滤
  • 剩余的行由 GROUP BY 子句分成组,并聚合
  • 然后通过 HAVING 子句再次过滤它们
  • 最后通过SELECT / ORDER BY、UPDATE或DELETE进行操作。

这里的重点不是 GROUP BY 必须命名 SELECT 中的所有列,但实际上恰恰相反——SELECT 不能包含任何尚未在 GROUP BY 中的列。

于 2010-06-20T17:00:02.803 回答
1

您的查询仅适用于 MySQL,因为您分组Person.cityKey但 select city.key。所有其他数据库都需要您使用聚合 like min(city.key),或添加City.keygroup 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组中的所有行都将具有相同的城市名称和键,因此使用ormin聚合无关紧要。

PS如果您只想计算不同的人,即使他们有多行,请尝试:

count(DISTINCT person.key)

代替

count(person.key)
于 2010-06-20T16:53:11.347 回答