计算多列的DISTINCT

有没有更好的方式来做这样的查询:

SELECT COUNT(*) FROM (SELECT DISTINCT DocumentId, DocumentSessionId FROM DocumentOutputItems) AS internalQuery 

我需要从这个表中计算不同项目的数量,但不同的是超过两列。

我的查询工作正常,但我想知道如果我可以得到最终结果只使用一个查询(不使用子查询)

如果您试图提高性能,可以尝试在两列的哈希值或连接值上创build持久计算列。

一旦持续,只要该列是确定性的,并且您使用的是“理智的”数据库设置,则可以对其进行索引和/或可以在其上创build统计信息。

我相信计算列的不同计数将等于您的查询。

编辑:从不太可靠的校验和查询我发现了一种方法来做到这一点(在SQL Server 2005中),对我来说工作很好,我可以根据需要使用尽可能多的列(通过将它们添加到CHECKSUM()函数)。 REVERSE()函数将ints变成varchars,使独特的更可靠

 SELECT COUNT(DISTINCT (CHECKSUM(DocumentId,DocumentSessionId)) + CHECKSUM(REVERSE(DocumentId),REVERSE(DocumentSessionId)) ) FROM DocumentOutPutItems 

你不喜欢现有的查询是什么? 如果您担心跨两列的DISTINCT不会返回唯一的排列,为什么不尝试呢?

这在Oracle中可以预料得到。

 SQL> select distinct deptno, job from emp 2 order by deptno, job 3 / DEPTNO JOB ---------- --------- 10 CLERK 10 MANAGER 10 PRESIDENT 20 ANALYST 20 CLERK 20 MANAGER 30 CLERK 30 MANAGER 30 SALESMAN 9 rows selected. SQL> select count(*) from ( 2 select distinct deptno, job from emp 3 ) 4 / COUNT(*) ---------- 9 SQL> 

编辑

我用分析去了一个不知疲倦的小巷,但答案令人沮丧地显而易见…

 SQL> select count(distinct concat(deptno,job)) from emp 2 / COUNT(DISTINCTCONCAT(DEPTNO,JOB)) --------------------------------- 9 SQL> 

编辑2

鉴于以下数据,上面提供的连接解决方​​案将错误计数:

 col1 col2 ---- ---- A AA AA A 

所以我们要包括一个分隔符…

 select col1 + '*' + col2 from t23 / 

显然,所选的分隔符必须是一个字符或一组字符,它们不能出现在任何一列中。

感觉如何?

select计数(*)
从
   (select count(*)cnt
   来自DocumentOutputItems
   通过DocumentId,DocumentSessionId)分组t1

可能就像你已经做的一样,但它避免了DISTINCT。

要以单个查询的forms运行,连接这些列,然后获取连接string的实例的不同数量。

 SELECT count(DISTINCT concat(DocumentId, DocumentSessionId)) FROM DocumentOutputItems; 

在MySQL中,你可以做同样的事情,没有连接步骤如下:

 SELECT count(DISTINCT DocumentId, DocumentSessionId) FROM DocumentOutputItems; 

这个特性在MySQL文档中提到:

http://dev.mysql.com/doc/refman/5.7/en/group-by-functions.html#function_count-distinct

这是一个没有子select的较短的版本:

 SELECT COUNT(DISTINCT DocumentId, DocumentSessionId) FROM DocumentOutputItems 

它在MySQL中工作正常,我认为优化器有一个更容易理解这个。

编辑:显然我误读MSSQL和MySQL – 抱歉,但也许它帮助无论如何。

你的查询没有问题,但你也可以这样做:

 WITH internalQuery (Amount) AS ( SELECT (0) FROM DocumentOutputItems GROUP BY DocumentId, DocumentSessionId ) SELECT COUNT(*) AS NumberOfDistinctRows FROM internalQuery 

当我为自己的问题谷歌search时,我发现这一点,发现如果你计算DISTINCT对象,你会得到正确的数字返回(我使用MySQL)

 SELECT COUNT(DISTINCT DocumentID) AS Count1, COUNT(DISTINCT DocumentSessionId) AS Count2 FROM DocumentOutputItems 

如果你只有一个字段“DISTINCT”,你可以使用:

 SELECT COUNT(DISTINCT DocumentId) FROM DocumentOutputItems 

并确实返回与原始相同的查询计划,如同使用SET SHOWPLAN_ALL ON进行testing。 然而,你使用两个字段,所以你可以尝试一些疯狂的事情:

  SELECT COUNT(DISTINCT convert(varchar(15),DocumentId)+'|~|'+convert(varchar(15), DocumentSessionId)) FROM DocumentOutputItems 

但如果涉及NULL,则会出现问题。 我只是坚持原来的查询。

希望这个作品,我在初级写真

 SELECT COUNT(*) FROM DocumentOutputItems GROUP BY DocumentId, DocumentSessionId 

我希望MS SQL也可以做一些像COUNT(DISTINCT A,B)。 但它不能。

起初JayTee的答案似乎是一个解决scheme后,我testing一些testingCHECKSUM()未能创build唯一的值。 一个简单的例子是,CHECKSUM(31,467,519)和CHECKSUM(69,1120,823)给出了相同的答案,即55。

然后我做了一些调查,发现微软不build议使用CHECKSUM进行变更检测。 在一些论坛中有人build议使用

 SELECT COUNT(DISTINCT CHECKSUM(value1, value2, ..., valueN) + CHECKSUM(valueN, value(N-1), ..., value1)) 

但这也不是很好。

您可以使用HQLBYTES()函数,如TSQL CHECKSUM难题中所build议的。 但是,这也有一个不返回独特结果的机会。

我会build议使用

 SELECT COUNT(DISTINCT CAST(DocumentId AS VARCHAR)+'-'+CAST(DocumentSessionId AS VARCHAR)) FROM DocumentOutputItems 

这下面的查询在MySQL上为我工作:

 SELECT COUNT(DISTINCT col_1,col_2,..) from table_name; 

在上面的查询中给出的列即 col_1,col_2对它们具有组合的UNIQUE约束。 这意味着在我的表table_name ,我已经创build了col_1 + col_2上的UNIQUE索引。

这是摆在Quora( https://www.quora.com/In-SQL-how-to-I-count-DISTINCT-over-multiple-columns )回答:

 select col1, col2, col3, count(*) from table group by col1, col2, col3 

我正在使用SAS进行这项工作,而SAS Proc SQL不喜欢带有多列的DISTINCT。