计算多列的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。