Nov*_*zky 184 sql t-sql sql-server
有没有更好的方法来执行这样的查询:
SELECT COUNT(*)
FROM (SELECT DISTINCT DocumentId, DocumentSessionId
FROM DocumentOutputItems) AS internalQuery
Run Code Online (Sandbox Code Playgroud)
我需要计算此表中不同项目的数量,但不同的是超过两列.
我的查询工作正常,但我想知道我是否只使用一个查询得到最终结果(不使用子查询)
Jas*_*ner 65
如果您尝试提高性能,可以尝试在两列的散列值或连接值上创建持久计算列.
一旦它被持久化,如果列是确定性的并且您正在使用"理智的"数据库设置,则可以对其进行索引和/或在其上创建统计数据.
我相信计算列的不同计数将等同于您的查询.
Jay*_*Tee 50
编辑:从不太可靠的校验和查询改变 我发现了一种方法(在SQL Server 2005中),这对我来说非常好,我可以使用尽可能多的列(通过将它们添加到CHECKSUM()函数).REVERSE()函数将ints转换为varchars以使distinct更加可靠
SELECT COUNT(DISTINCT (CHECKSUM(DocumentId,DocumentSessionId)) + CHECKSUM(REVERSE(DocumentId),REVERSE(DocumentSessionId)) )
FROM DocumentOutPutItems
Run Code Online (Sandbox Code Playgroud)
APC*_*APC 28
您不喜欢的现有查询是什么?如果您担心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>
Run Code Online (Sandbox Code Playgroud)
编辑
我带着分析走了一条死胡同,但答案却显得令人沮丧......
SQL> select count(distinct concat(deptno,job)) from emp
2 /
COUNT(DISTINCTCONCAT(DEPTNO,JOB))
---------------------------------
9
SQL>
Run Code Online (Sandbox Code Playgroud)
编辑2
鉴于以下数据,上面提供的连接解决方案将错误计算:
col1 col2
---- ----
A AA
AA A
Run Code Online (Sandbox Code Playgroud)
所以我们要包括一个分隔符......
select col1 + '*' + col2 from t23
/
Run Code Online (Sandbox Code Playgroud)
显然,所选的分隔符必须是一个字符或一组字符,它们永远不会出现在任一列中.
Tre*_*ins 14
怎么样的:
select count(*) from (select count(*) cnt from DocumentOutputItems group by DocumentId, DocumentSessionId) t1
可能只是和你一样,但它避免了DISTINCT.
spe*_*nk1 13
要作为单个查询运行,请连接列,然后获取连接字符串的不同实例计数.
SELECT count(DISTINCT concat(DocumentId, DocumentSessionId)) FROM DocumentOutputItems;
Run Code Online (Sandbox Code Playgroud)
在MySQL中,您可以执行相同的操作,而无需连接步骤,如下所示:
SELECT count(DISTINCT DocumentId, DocumentSessionId) FROM DocumentOutputItems;
Run Code Online (Sandbox Code Playgroud)
MySQL文档中提到了此功能:
http://dev.mysql.com/doc/refman/5.7/en/group-by-functions.html#function_count-distinct
kar*_*aze 13
许多(大多数?)SQL 数据库可以使用像值这样的元组,因此您可以这样做:
SELECT COUNT(DISTINCT (DocumentId, DocumentSessionId))
FROM DocumentOutputItems;
如果您的数据库不支持此功能,则可以根据 @oncel-umut-turer 的 CHECKSUM 或其他标量函数的建议进行模拟,以提供良好的唯一性例如
COUNT(DISTINCT CONCAT(DocumentId, ':', DocumentSessionId))。
元组的一个相关用途是执行IN查询,例如:
SELECT * FROM DocumentOutputItems
WHERE (DocumentId, DocumentSessionId) in (('a', '1'), ('b', '2'));
小智 8
我已经使用了这种方法并且它对我有用。
SELECT COUNT(DISTINCT DocumentID || DocumentSessionId)
FROM DocumentOutputItems
Run Code Online (Sandbox Code Playgroud)
就我而言,它提供了正确的结果。
这是一个没有子选择的较短版本:
SELECT COUNT(DISTINCT DocumentId, DocumentSessionId) FROM DocumentOutputItems
Run Code Online (Sandbox Code Playgroud)
它在MySQL中运行良好,我认为优化器更容易理解这个.
编辑:显然我误读了MSSQL和MySQL - 抱歉,但也许它有帮助.
小智 5
如果您正在使用固定长度的数据类型,则可以通过强制转换来binary非常轻松且快速地完成此操作。假设DocumentId和DocumentSessionId都是ints,因此长度为 4 个字节......
SELECT COUNT(DISTINCT CAST(DocumentId as binary(4)) + CAST(DocumentSessionId as binary(4)))
FROM DocumentOutputItems
Run Code Online (Sandbox Code Playgroud)
我的具体问题要求我将 a 除以SUM各种COUNT外键和日期字段的不同组合,按另一个外键分组,偶尔按某些值或键进行过滤。表非常大,使用子查询会大大增加查询时间。由于其复杂性,统计根本不是一个可行的选择。该CHECKSUM解决方案的转换速度也太慢,特别是由于数据类型不同,我不能冒它不可靠性的风险。
然而,使用上述解决方案几乎没有增加查询时间(与仅使用 相比SUM),并且应该是完全可靠的!它应该能够帮助处于类似情况的其他人,所以我将其发布在这里。