这不起作用:
select count(distinct colA, colB) from mytable
我知道我可以简单地解决这个问题,使一个双重选择。
select count(*) from ( select distinct colA, colB from mytable )
有没有什么方法可以做到这一点,而不必做子选择?
nr7wwzry1#
子查询是我推荐的标准解决方案。基于级联的解决方案,除了在出现危险字符时容易出错之外,性能也可能更差。注意:如果你收集了一些关于如何避免子查询的模糊解决方案,这里也可以使用窗口函数(不用于生产-你的代码评审员不会因此称赞你):
select distinct count(*) over () from my_table group by colA, colB
jaxagkaj2#
[TL;DR]只需使用子查询。如果你试图使用连接,那么你需要确保你用一个永远不会出现在值中的字符串来分隔术语,否则你会发现非独特的术语组合在一起。举例来说:如果你有两个数字列,那么使用COUNT(DISTINCT col1 || col2)将把1||23和12||3组合在一起,并把它们算作一个组。你可以使用COUNT(DISTINCT col1 || '-' || col2),但如果列是字符串值,并且你有'ab-'||'-'||'c'和'ab'||'-'||'-c',那么,再次,它们一旦连接起来就相同。最简单的方法是使用子查询。如果你不能这样做,那么你可以通过字符串连接来合并组合列,但是你需要分析列的内容,并选择一个没有出现在你的字符串中的字符串,否则你的结果可能是错误的。更好的方法是确保带check约束的子字符串中永远不会出现这个字符串。
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;
o4tp2gmn3#
只是为了好玩,你可以(ab)使用窗口函数和限制子句。这些是在分组后评估的。所以:
SELECT COUNT(*) OVER() FROM t GROUP BY col_a, col_b OFFSET 0 ROWS FETCH NEXT 1 ROWS ONLY
rqqzpn5f4#
如果你试图不惜一切代价避免子选择,一个变体是将它们连接起来:
SELECT count(DISTINCT concat(colA, colB)) FROM mytable;
tct7dpnv5#
把它们连接起来。
Select count(distinct colA ||'-'|| colB) from mytable;
omhiaaxx6#
还有一个使用JSON的方法:
SELECT count(DISTINCT json_object('colA', colA, 'colB', colB)) FROM mytable;
6条答案
按热度按时间nr7wwzry1#
子查询是我推荐的标准解决方案。基于级联的解决方案,除了在出现危险字符时容易出错之外,性能也可能更差。
注意:如果你收集了一些关于如何避免子查询的模糊解决方案,这里也可以使用窗口函数(不用于生产-你的代码评审员不会因此称赞你):
jaxagkaj2#
[TL;DR]只需使用子查询。
如果你试图使用连接,那么你需要确保你用一个永远不会出现在值中的字符串来分隔术语,否则你会发现非独特的术语组合在一起。
举例来说:如果你有两个数字列,那么使用
COUNT(DISTINCT col1 || col2)
将把1||23
和12||3
组合在一起,并把它们算作一个组。你可以使用
COUNT(DISTINCT col1 || '-' || col2)
,但如果列是字符串值,并且你有'ab-'||'-'||'c'
和'ab'||'-'||'-c'
,那么,再次,它们一旦连接起来就相同。最简单的方法是使用子查询。
如果你不能这样做,那么你可以通过字符串连接来合并组合列,但是你需要分析列的内容,并选择一个没有出现在你的字符串中的字符串,否则你的结果可能是错误的。更好的方法是确保带check约束的子字符串中永远不会出现这个字符串。
然后又道:
o4tp2gmn3#
只是为了好玩,你可以(ab)使用窗口函数和限制子句。这些是在分组后评估的。所以:
rqqzpn5f4#
如果你试图不惜一切代价避免子选择,一个变体是将它们连接起来:
tct7dpnv5#
把它们连接起来。
omhiaaxx6#
还有一个使用JSON的方法: