MYSQL:带GROUP BY,LEFT JOIN和WHERE子句的COUNT不返回零值

时间:2010-04-28 14:19:53

标签: sql mysql

我确信这有一个非常简单的答案,但我似乎无法找到它(不知道要搜索什么!)。查询的标准计数/分组可能如下所示:

SELECT COUNT(`t2`.`name`) 
FROM `table_1` `t1` 
    LEFT JOIN `table_2` `t2` ON `t1`.`key_id` = `t2`.`key_id` 
WHERE `t1`.`another_column` = 123 

并且按预期工作,如果没有找到行则返回0。但是:

SELECT COUNT(`t2`.`name`) 
FROM `table_1` `t1` 
    LEFT JOIN `table_2` `t2` ON `t1`.`key_id` = `t2`.`key_id` 
WHERE `t1`.`another_column` = 123 
GROUP BY `t1`.`any_col` 

仅在table_1中至少有一行时才有效,如果行数为零,则无法返回空结果集。我真的希望这回到0!有谁启发我这个?如果您在伦敦,可以提供啤酒; - )

2 个答案:

答案 0 :(得分:4)

它返回零行的原因是您要对table_1中的值进行分组。表1中没有值,没有要返回的行。换句话说,如果您从GROUP BY返回查询中的t1.any_col,如下所示:

SELECT `t1`.`any_col`, COUNT(`t2`.`name`) 
FROM `table_1` `t1` 
    LEFT JOIN `table_2` `t2` ON `t1`.`key_id` = `t2`.`key_id` 
WHERE `t1`.`another_column` = 123 
GROUP BY `t1`.`any_col` 

没有行时t1.any_col会显示什么?实现所需内容的唯一方法是将结果与另一个检查table_1中没有行的查询结合起来。在这个例子中,我使用INFORMATION_SCHEMA视图只是为了得到我可以查询的内容。

SELECT COUNT(`t2`.`name`) 
FROM `table_1` `t1` 
    LEFT JOIN `table_2` `t2` ON `t1`.`key_id` = `t2`.`key_id` 
WHERE `t1`.`another_column` = 123 
GROUP BY `t1`.`any_col` 
UNION ALL
SELECT 0
FROM INFORMATION_SCHEMA.TABLES
Where Not Exists( Select 1 From `table_1` )
LIMIT 1

答案 1 :(得分:3)

这是更好的解决方案:

SELECT COUNT(*) FROM
(SELECT `t2`.`name`
FROM `table_1` `t1` 
    LEFT JOIN `table_2` `t2` ON `t1`.`key_id` = `t2`.`key_id` 
WHERE `t1`.`another_column` = 123 
GROUP BY `t1`.`any_col`) tmp

您只需在查询周围包裹SELECT COUNT(*)

问题是COUNT()从含义“给我计算结果集中的行数”改为聚合函数,意思是“给我一个符合我标准的每个组的行数”与GROUP BY子句一起使用。在您的情况下,由于another_column = 123的组没有行,因此不返回任何内容。

如果你将它包装在另一个SELECT COUNT(*)中,你再次说,“给我一个结果集中的行数。”

在第一个查询中,COUNT()正在使用GROUP BY。但是如果没有指定条件,则至少从table_1返回一行。由于没有相应的table_2记录,因此COUNT()的NULL值为0。不要使用第一个查询。虽然它会回归你所期待的,但这只是偶然的。要使查询有意义,您应在WHERE子句中指定t1.another_column的条件。

第二个查询有效,因为您要求结果集的行计数。由于没有t1.another_column = 123的行,因此返回0行,COUNT()的计算结果为0。