在不折叠NULL值的情况下计算MySQL中的不同值

时间:2012-11-28 12:12:39

标签: mysql sql count null aggregate-functions

我的表a有两个字段:id(PK)和f

考虑以下记录:

id | f
1  | NULL
2  | 'foo'
3  | 'bar'
4  | NULL
5  | 'foo'
6  | 'baz'

我想检索并计算具有不同f值的所有记录,包括每条记录WHERE f IS NULL。根据此条件,查询应返回除#5之外的所有记录,因为相同的值已包含在集合中,总计数将为5.

我用来检索所有记录的查询如下所示:

SELECT CASE WHEN EXISTS (SELECT id FROM a a2 WHERE a2.f = a.f AND a.id < a2.id) THEN 1 END AS not_distinct FROM a HAVING not_distinct IS NULL

如果可以改进此查询,我欢迎任何反馈。无论如何,主要的问题是计数。显然添加COUNT(*)在这里没有用,我完全忘记了过滤后如何计算记录。

3 个答案:

答案 0 :(得分:9)

这可能对您有用:

select count(distinct ifnull(f, id))
from a

请注意,此查询假定f值永远不是id值,并且基于样本数据和经验,这是合理的。

编辑:

我考虑过这个问题而且还有一个简单的更简单的方法:

select count(distinct f) + sum(f is null) from a;

您可以看到running on sqlfiddle

这是有效的,因为distinct抛出空值,sum(condition)计算条件为真的次数,因为在mysql中,true为1,false为0

答案 1 :(得分:3)

NOT EXISTS子句中使用WHERE

SELECT count(*)
FROM   a
WHERE  NOT EXISTS (SELECT * FROM a a2 WHERE a2.f = a.f AND a2.id < a.id);

通过这种方式,您还可以获得实际行 - 如果您需要的数量超过裸数:

SELECT *
FROM   a
WHERE  NOT EXISTS (SELECT * FROM a a2 WHERE a2.f = a.f AND a2.id < a.id)

=运算符可确保包含带有f IS NULL所有行。你已经在查询中有了这个。

-> sqlfiddle

这些都不起作用:

SELECT DISTINCT f FROM a;

SELECT * FROM a GROUP BY f;

..因为两者都会折叠NULL值,而你想要

  

每条记录WHERE f为NULL。

答案 2 :(得分:0)

    UPDATE comments SET view =     
                              (SELECT COUNT(DISTINCT browser, ip, ifnull(user_id, 0)) 
                              FROM counters WHERE item_type=comments.item_type )
    WHERE id=1