我有两个问题。其中一个对我有意义,另一个则没有。第一个:
SELECT gender AS 'Gender', count(*) AS '#'
FROM registrations
GROUP BY gender WITH ROLLUP
这给了我这个:
Gender #
Female 20
Male 19
NULL 39
所以,我得到了计数和总数。我的期望。下一个:
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
结果相同。但为什么我要把乌兹别克斯坦作为总数?
答案 0 :(得分:37)
但为什么我要获得乌兹别克斯坦的总数?
因为您没有选择您正在进行GROUPING BY的项目。如果你说:
GROUP BY c.printable_name
你会得到预期的NULL。但是,您要按其他列进行分组,以便MySQL不知道printable_name正在参与汇总组,并在所有注册的连接中选择该列中的任何旧值。 (所以你可能会看到除乌兹别克斯坦之外的其他国家。)
这是更广泛问题的一部分,MySQL允许你在GROUP BY查询中选择SELECT。例如,您可以说:
SELECT gender FROM registrations GROUP BY country;
并且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
没问题,因为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。因此它会使有效查询失败,使其通常无用。)
答案 1 :(得分:0)
当您使用JOIN方法时,数组的以下NULL元素将具有先前NOT NULL元素的值。但我不确定。这是我在PHP中使用它时的经验。
嗯...还有另一个问题...... '国家'因为它是表格的名称。因此改变别的东西。然后最后的结果将显示NULL。 这是我的建议:
$result = mysql_query("SELECT c.printable_name AS 'countryp', count(*) AS '#'
FROM registrations r, country c WHERE r.country = c.country_id
GROUP BY countryp WITH ROLLUP");
while($row = @mysql_fetch_array($result)) {
$r1 = $row["countryp"];
$r2 = $row["#"];
if ($r1 == NULL) $r1 = 'Total';
echo "$r1 $r2<br />";
}
答案 2 :(得分:0)
SELECT ifnull(c.printable_name, "Total Registration = ") AS 'Country', count(*) AS '#'
FROM registrations r
INNER JOIN country c ON r.country = c.country_id
GROUP BY country WITH ROLLUP;
这将打印'总注册数= 39 ',并且将是最后一行/记录。