tutorial transact query examples ejemplos sql sql-server tsql

query - transact sql tutorial



Contando DISTINCT sobre múltiples columnas (15)

¿Qué pasa con su consulta existente que no le gusta? Si le preocupa que DISTINCT en dos columnas no devuelva solo las permutaciones únicas, ¿por qué no intentarlo?

Ciertamente funciona como es de esperar en 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>

editar

Bajé por un callejón sin salida con análisis, pero la respuesta fue tristemente obvia ...

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

editar 2

Teniendo en cuenta los siguientes datos, la solución de concatenación provista arriba contrastará:

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

Entonces, para incluir un separador ...

select col1 + ''*'' + col2 from t23 /

Obviamente, el separador elegido debe ser un personaje, o conjunto de caracteres, que nunca puede aparecer en ninguna columna.

¿Hay una mejor manera de hacer una consulta como esta?

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

Necesito contar el número de elementos distintos de esta tabla, pero el distinto es más de dos columnas.

Mi consulta funciona bien pero me preguntaba si puedo obtener el resultado final con solo una consulta (sin usar una sub consulta)


¿Qué tal algo así como:

select count(*) from (select count(*) cnt from DocumentOutputItems group by DocumentId, DocumentSessionId) t1

Probablemente haga lo mismo que usted ya, pero evita el DISTINCT.


Aquí hay una versión más corta sin la subselección:

SELECT COUNT(DISTINCT DocumentId, DocumentSessionId) FROM DocumentOutputItems

Funciona bien en MySQL, y creo que al optimizador le resulta más fácil entenderlo.

Editar: Aparentemente, leí mal MSSQL y MySQL, disculpe por eso, pero tal vez ayude de todos modos.


Encontré esto cuando busqué en Google mi propio problema, encontré que si cuenta objetos DISTINCT, obtiene el número correcto devuelto (estoy usando MySQL)

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


Espero que esto funcione, estoy escribiendo en prima vista

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


Esta consulta a continuación me funcionó en MySQL:

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

Las columnas dadas en la consulta anterior viz. col_1, col_2 tiene una restricción UNIQUE combinada en ellos. Eso significa que en mi tabla table_name , he creado un índice UNIQUE en col_1 + col_2 .



Esto funciona para mi. En oráculo:

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

En jpql:

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


No hay nada de malo con su consulta, pero también podría hacerlo de esta manera:

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


Ojalá MS SQL también pudiera hacer algo como COUNT (DISTINCT A, B). Pero no puede.

Al principio, la respuesta de JayTee me pareció una solución, luego de algunas pruebas, CHECKSUM () no pudo crear valores únicos. Un ejemplo rápido es que tanto CHECKSUM (31,467,519) como CHECKSUM (69,1120,823) dan la misma respuesta que es 55.

Luego investigué y descubrí que Microsoft NO recomienda el uso de CHECKSUM para fines de detección de cambios. En algunos foros, algunos sugirieron usar

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

pero esto tampoco es cómodo.

Puede utilizar la función HASHBYTES () como se sugiere en el enigma TSQL CHECKSUM . Sin embargo, esto también tiene una pequeña posibilidad de no devolver resultados únicos.

Sugeriría usar

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


Para ejecutar como una sola consulta, concatenar las columnas, luego obtener el recuento distinto de las instancias de la cadena concatenada.

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

En MySQL puede hacer lo mismo sin el paso de concatenación de la siguiente manera:

SELECT count(DISTINCT DocumentId, DocumentSessionId) FROM DocumentOutputItems;

Esta característica se menciona en la documentación de MySQL:

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


Qué tal esto,

Select DocumentId, DocumentSessionId, count(*) as c from DocumentOutputItems group by DocumentId, DocumentSessionId;

Esto nos dará la cuenta de todas las combinaciones posibles de DocumentId y DocumentSessionId


Si intenta mejorar el rendimiento, puede intentar crear una columna calculada persistente en un valor hash o concatenado de las dos columnas.

Una vez que se mantiene, siempre que la columna sea determinista y utilice una configuración de base de datos "sensata", puede indexarse ​​y / o crearse estadísticas en ella.

Creo que un recuento distinto de la columna calculada sería equivalente a su consulta.


si tuvieras solo un campo para "DISTINCT", podrías usar:

SELECT COUNT(DISTINCT DocumentId) FROM DocumentOutputItems

y eso devuelve el mismo plan de consulta que el original, tal como se probó con SET SHOWPLAN_ALL ON. Sin embargo, estás usando dos campos para que puedas probar algo loco como:

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

pero tendrás problemas si hay NULL involucrados. Me quedaría con la consulta original.


Editar: alterado a partir de la consulta de suma de comprobación menos que confiable que he descubierto una forma de hacer esto (en SQL Server 2005) que funciona muy bien para mí y puedo usar tantas columnas como sea necesario (agregándolas a la función CHECKSUM ()). La función REVERSE () convierte las entradas en varchars para hacer que el distinto sea más confiable

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