【问题标题】:Count distinct values in MySQL without folding NULL values在不折叠 NULL 值的情况下计算 MySQL 中的不同值
【发布时间】:2012-11-28 12:12:39
【问题描述】:

我有一个表 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(*) 在这里无济于事,我完全不知道如何在过滤后计算记录。

【问题讨论】:

  • 您能否提供您希望以 o/p 形式获得的示例数据?
  • @AjithSasidharan:问题已经很清楚了:the query should return every record except #5, because the same value is already included in the set, and the total count would be 5.
  • 是的,现在就去要求。

标签: mysql sql count null aggregate-functions


【解决方案1】:

有一个非常简单的方法可能对你有用:

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 中,真为1,假为0

【讨论】:

  • 虽然您的解决方案通常在性能方面更好,但我选择了 Erwin 的答案,因为它在当前情况下更适合我的需求。还是谢谢!
  • @package 请参阅编辑后的答案,了解另一种非常简单的方法,它也会表现良好,但不是“聪明的裤子”。 (顺便说一句,您选择的答案总是很糟糕)。
【解决方案2】:

WHERE 子句中使用NOT EXISTS

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 IS NULL。

【讨论】:

  • 这个解决方案似乎很明显,我想知道为什么我自己没有弄清楚。非常感谢,效果很好。
  • 解决方案就是这样:一旦您拥有它们,大多数解决方案看起来都非常明显。 :)
【解决方案3】:
    UPDATE comments SET view =     
                              (SELECT COUNT(DISTINCT browser, ip, ifnull(user_id, 0)) 
                              FROM counters WHERE item_type=comments.item_type )
    WHERE id=1

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-25
    • 1970-01-01
    • 2015-02-12
    • 1970-01-01
    • 2022-07-21
    相关资源
    最近更新 更多