如何对多列进行计数(不同)

How to do count(distinct) for multiple columns

这不起作用:

select count(distinct colA, colB) from mytable

我知道我可以简单地通过制作一个双 select.

来解决这个问题
select count(*) from (
    select distinct colA, colB from mytable
)

有没有办法不用做子select?

将它们连接起来。

Select count(distinct colA ||'-'|| colB) from mytable;

如果您试图不惜一切代价避免子选择,一种变体是将它们连接起来:

SELECT count(DISTINCT concat(colA, colB)) FROM mytable;

[TL;DR] 只需使用子查询即可。


如果您尝试使用串联,那么您需要确保使用永远不会出现在值中的字符串分隔术语,否则您会发现不明确的术语组合在一起。

例如:如果您有两个数字列,那么使用 COUNT(DISTINCT col1 || col2) 会将 1||2312||3 组合在一起,并将它们计为一组。

您可以使用 COUNT(DISTINCT col1 || '-' || col2) 但如果列是字符串值并且您有 'ab-'||'-'||'c''ab'||'-'||'-c' 那么,再一次,它们在连接后将是相同的。

最简单的方法是使用子查询。

如果您不能这样做,那么您可以通过字符串连接来组合列,但您需要分析列的内容并选择一个没有出现在您的字符串中的分隔符,否则您的结果可能是错误的。更好的是确保分隔符永远不会出现在带有检查约束的子字符串中。

ALTER TABLE mytable ADD CONSTRAINT mytable__col1__chk CHECK (col1 NOT LIKE '%¬%');
ALTER TABLE mytable ADD CONSTRAINT mytable__col2__chk CHECK (col2 NOT LIKE '%¬%');

然后:

SELECT COUNT(DISTINCT col1 || '¬' || col2)
FROM   mytable;

子查询也是我推荐的标准解决方案。基于串联的解决方案,除非它们在出现危险字符时容易出错,否则性能也可能更差。

注意:如果您收集了如何避免子查询的晦涩解决方案,window 也可以在此处使用函数(不在生产中使用 - 您的代码审阅者不会因此表扬你):

select distinct count(*) over ()
from my_table
group by colA, colB

只是为了好玩,您可以(滥用)使用 window 函数和限制子句。这些在分组后进行评估。所以:

SELECT COUNT(*) OVER()
FROM t
GROUP BY col_a, col_b
OFFSET 0 ROWS FETCH NEXT 1 ROWS ONLY