是否有更好的方法来执行这样的查询:

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

我需要数一下这个表中不同项的数量,但不同项超过两列。

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


当前回答

一些SQL数据库可以使用元组表达式,所以你可以这样做:

SELECT COUNT(DISTINCT (DocumentId, DocumentSessionId))
      FROM DocumentOutputItems;

如果你的数据库不支持这个,可以根据@oncel-umut-的建议来模拟CHECKSUM或其他提供良好唯一性的标量函数。 COUNT(DISTINCT CONCAT(documententid, ':', DocumentSessionId)))。

MySQL特别支持COUNT(DISTINCT expr, expr,…),这是非sql标准语法。它还指出,在标准SQL中,您必须在COUNT(DISTINCT…)中对所有表达式进行连接。

元组的一个相关用法是执行IN查询,例如:

SELECT * FROM DocumentOutputItems
WHERE (DocumentId, DocumentSessionId) in (('a', '1'), ('b', '2'));

其他回答

编辑:从不太可靠的仅校验和查询更改 我发现了一种方法来做到这一点(在SQL Server 2005中),这对我来说很好,我可以使用尽可能多的列,因为我需要(通过将它们添加到CHECKSUM()函数)。REVERSE()函数将int类型转换为varchars类型,以使distinct类型更加可靠

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

这段代码使用distinct on 2参数,并提供特定于这些不同值的行数计数。它在MySQL中为我工作,就像一个魅力。

select DISTINCT DocumentId as i,  DocumentSessionId as s , count(*) 
from DocumentOutputItems   
group by i ,s;

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

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

若要作为单个查询运行,请连接列,然后获取连接的字符串的不同实例计数。

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

这对我很管用。在oracle中:

SELECT SUM(DECODE(COUNT(*),1,1,1))
FROM DocumentOutputItems GROUP BY DocumentId, DocumentSessionId;

在jpql:

SELECT SUM(CASE WHEN COUNT(i)=1 THEN 1 ELSE 1 END)
FROM DocumentOutputItems i GROUP BY i.DocumentId, i.DocumentSessionId;