为什么 COUNT(DISTINCT (*)) 不起作用?

9

我仍然感到惊讶的是,为什么这样简单的查询不起作用:

SELECT COUNT(DISTINCT *) FROM dbo.t_test     

相反,

SELECT COUNT(DISTINCT col1) FROM dbo.t_test

并且

SELECT DISTINCT * FROM dbo.t_test 

运行正常。

那有什么替代方案吗?

编辑:

DISTINCT * 会检查(col1、col2等)的组合键的唯一性,并返回这些行。我预期 COUNT(DISTINCT *) 只返回这些行的数量。我错过了什么吗?


“不起作用”的是什么? - Gert Arnold
5个回答

22

这不起作用是因为根据文档,在COUNT(DISTINCT ...)中只允许指定单个表达式:

COUNT ( { [ [ ALL | DISTINCT ] expression ] | * } )

仔细观察会发现允许的语法中不包括COUNT(DISTINCT *)

另一种选择是这样的:

SELECT COUNT(*) FROM
(
    SELECT DISTINCT * FROM dbo.t_test 
) T1

8
事实上,SQL(Server)或任何其他SQL实现都不应该在太阳下做所有事情。限制SQL语法到某些元素是有原因的,从解析层到查询优化,到结果可预测性,以至于常识。
COUNT聚合函数通常被实现为具有单个项门控的流式聚合,无论是*(记录计数,只需使用静态令牌),还是colname(仅在非空时递增令牌),或者distinct colname(一个带有一个键的哈希/桶)。
当您要求COUNT(DISTINCT *)或那件事COUNT(DISTINCT a,b,c)时,如果一些RDBMS认为有必要实现它,那么肯定可以为您完成;但是这是(1)不太常见的(2)会给解析器增加工作(3)会增加COUNT实现的复杂性。
马克有正确的替代方案

5
除了其他人说的之外:
需要注意的一点是,在具有主键的表上执行count(distinct *)(如果被允许)将与select count(*)相同。
这是因为distinct *包括PK列,因此每行都不同于其他每行。
由于每个非平凡表都应该有一个主键(只有极少数例外情况),所以count(distinct *)可以用count(*)“替换”。

4

举个简单的例子,假设你有两列,A和B。

A    B
1    100
2    100
3    100

有三个不同的A值,但只有一个不同的B值。使用COUNT(DISTINCT *)无法返回单一且有意义的值,因此这种语法是行不通的。


谢谢Joe!我已根据您的解释更新了问题。 - rkg

-1

我曾经遇到过同样的问题,最终找到了这个解决方案

假设你有类似这样的东西

PID 名称
1 牛奶
1 奶酪
1
2 黄油
2 奶油
3 蜂蜜

而你的表格名为“food” 你可以像这样编写代码

    select distinct count(dbo.food.PID) as count,a.PID from dbo.food
    inner join (select distinct dbo.food.PID as PID from db.food) a       
on dbo.food.PID=a.PID where a.PID=dbo.food.PID 
 group by a.PID,dbo.food.PID

这将显示类似于以下内容

计数 PID
3 1
2 2
1 1

这个回答怎么解决问题的?它并没有解释关于DISTINCT运算符的任何内容,这才是问题所在。而且,这种方法非常牵强地实现了一个简单的分组+计数,输出结果中甚至还有一个错别字。 - Gert Arnold

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接