我有两个问题.其中一个对我有意义,另一个则没有.第一:
SELECT gender AS 'Gender', count(*) AS '#'
FROM registrations
GROUP BY gender WITH ROLLUP
Run Code Online (Sandbox Code Playgroud)
这给了我这个:
Gender #
Female 20
Male 19
NULL 39
Run Code Online (Sandbox Code Playgroud)
所以,我得到了计数和总数.我的期望.下一个:
SELECT c.printable_name AS 'Country', count(*) AS '#'
FROM registrations r
INNER JOIN country c ON r.country = c.country_id
GROUP BY country WITH ROLLUP
Country #
Denmark 9
Norway 10
Sweden 18
United States 1
Uzbekistan 1
Uzbekistan 39
Run Code Online (Sandbox Code Playgroud)
结果相同.但为什么我要总共得到乌兹别克斯坦?
bob*_*nce 38
但为什么我要总共得到乌兹别克斯坦?
因为您没有选择您正在进行GROUPING BY的项目.如果你说:
GROUP BY c.printable_name
Run Code Online (Sandbox Code Playgroud)
你会得到预期的NULL.但是,您要按其他列进行分组,因此MySQL不知道printable_name正在参与汇总组,并在所有注册的连接中选择该列中的任何旧值.(所以你可能会看到除乌兹别克斯坦之外的其他国家.)
这是一个更广泛问题的一部分,MySQL允许你在GROUP BY查询中选择SELECT.例如,您可以说:
SELECT gender FROM registrations GROUP BY country;
Run Code Online (Sandbox Code Playgroud)
即使国家和性别之间没有直接的因果关系(又称"功能依赖"),MySQL也会乐意为每个国家的注册选择一个性别价值观.其他DBMS将拒绝上述命令,理由是每个国家不保证一个性别.(*)
现在,这个:
SELECT c.printable_name AS 'Country', count(*) AS '#'
FROM registrations r
INNER JOIN country c ON r.country = c.country_id
GROUP BY country
Run Code Online (Sandbox Code Playgroud)
没问题,因为r.country和c.printable_name之间存在功能依赖关系(假设您已正确将country_id描述为PRIMARY KEY).
然而,MySQL的WITH ROLLUP扩展在它的工作方式上有点像黑客.在末尾的汇总行阶段,它在整个预分组结果集上运行以获取其值,然后将group-by列设置为NULL.它也不会使对该列具有功能依赖性的其他列无效.它可能应该,但MySQL目前并不真正了解功能依赖的整个事情.
因此,如果您选择c.printable_name,它将显示它随机选择的任何国家/地区名称值,如果您选择c.country_id,它将显示它随机选择的任何国家/地区ID - 即使c.country_id是加入条件,因此必须是与r.country相同,为NULL!
你可以做些什么来解决这个问题:
(*:MySQL有一个SQL_MODE选项ONLY_FULL_GROUP_BY应该解决这个问题,但它太过分了,只允许你从GROUP BY中选择列,而不是对GROUP BY具有功能依赖性的列.所以它会使有效查询也会失败,因此通常无用.)
| 归档时间: |
|
| 查看次数: |
41588 次 |
| 最近记录: |