是否有更好的方法来执行这样的查询:
SELECT COUNT(*)
FROM (SELECT DISTINCT DocumentId, DocumentSessionId
FROM DocumentOutputItems) AS internalQuery
我需要数一下这个表中不同项的数量,但不同项超过两列。
我的查询工作得很好,但我想知道我是否可以只使用一个查询(不使用子查询)得到最终结果
是否有更好的方法来执行这样的查询:
SELECT COUNT(*)
FROM (SELECT DISTINCT DocumentId, DocumentSessionId
FROM DocumentOutputItems) AS internalQuery
我需要数一下这个表中不同项的数量,但不同项超过两列。
我的查询工作得很好,但我想知道我是否可以只使用一个查询(不使用子查询)得到最终结果
当前回答
如果你只有一个字段可以“DISTINCT”,你可以使用:
SELECT COUNT(DISTINCT DocumentId)
FROM DocumentOutputItems
并且返回与原始的相同的查询计划,正如SET SHOWPLAN_ALL ON测试的那样。然而,你正在使用两个字段,所以你可以尝试一些疯狂的东西,如:
SELECT COUNT(DISTINCT convert(varchar(15),DocumentId)+'|~|'+convert(varchar(15), DocumentSessionId))
FROM DocumentOutputItems
但如果涉及到null,就会出现问题。我还是用原来的问题吧。
其他回答
你的查询没有问题,但你也可以这样做:
WITH internalQuery (Amount)
AS
(
SELECT (0)
FROM DocumentOutputItems
GROUP BY DocumentId, DocumentSessionId
)
SELECT COUNT(*) AS NumberOfDistinctRows
FROM internalQuery
比如:
select count(*) from (select count(*) cnt from DocumentOutputItems group by DocumentId, DocumentSessionId) t1
可能只是做了和你已经做的一样的事情,但是它避免了DISTINCT。
下面是不带subselect的简短版本:
SELECT COUNT(DISTINCT DocumentId, DocumentSessionId) FROM DocumentOutputItems
它在MySQL中工作得很好,我认为优化器更容易理解这一点。
编辑:显然我误解了MSSQL和MySQL -对不起,但也许它有帮助。
如果您试图提高性能,可以尝试在两个列的散列或连接值上创建持久计算列。
一旦它被持久化,只要列是确定的,并且您使用的是“正常的”数据库设置,就可以对其建立索引和/或在其上创建统计信息。
我相信计算列的不同计数将等效于您的查询。
您不喜欢现有查询的哪些方面?如果您担心两列之间的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>
edit
我进入了分析的死胡同,但答案很明显……
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
/
显然,所选择的分隔符必须是一个字符或一组字符,它不能出现在任何一列中。