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

问题描述 投票:0回答:6

这不起作用:

select count(distinct colA, colB) from mytable

我知道我可以通过双重选择来简单地解决这个问题。

select count(*) from (
    select distinct colA, colB from mytable
)

我是否可以做到这一点而不必进行子选择?

sql oracle aggregate-functions
6个回答
2
投票

子查询是我也推荐的标准解决方案。基于串联的解决方案除了在出现危险字符时容易出错之外,性能也可能较差。

注意:如果您收集了如何避免子查询的晦涩解决方案,这里也可以使用窗口函数(不要在生产中使用 - 您的代码审查者不会为此赞扬您):

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

1
投票

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


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

例如:如果您有两个数字列,则使用

COUNT(DISTINCT col1 || col2)
会将
1||23
12||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;

1
投票

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

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

0
投票

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

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

0
投票

将它们连接起来。

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

0
投票

还有另一种使用 JSON 的选项:

SELECT count(DISTINCT
 json_group_array(json_object('colA', colA, 'colB', colB))
)
FROM mytable;
© www.soinside.com 2019 - 2024. All rights reserved.