¿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 elemento distintivo está sobre dos columnas.
Mi consulta funciona bien, pero me preguntaba si puedo obtener el resultado final usando solo una consulta (sin usar una subconsulta)
sql
sql-server
performance
tsql
query-optimization
Novitzky
fuente
fuente
Respuestas:
Si está intentando mejorar el rendimiento, puede intentar crear una columna calculada persistente en un valor hash o concatenado de las dos columnas.
Una vez que persiste, siempre que la columna sea determinista y esté utilizando configuraciones de base de datos "sanas", se puede indexar y / o se pueden crear estadísticas en ella.
Creo que un recuento distinto de la columna calculada sería equivalente a su consulta.
fuente
Editar: alterado de la consulta de suma de comprobación poco confiable, descubrí una forma de hacer esto (en SQL Server 2005) que funciona bastante bien para mí y puedo usar tantas columnas como necesite (agregándolas a la función CHECKSUM ()). La función REVERSE () convierte los ints en varchars para hacer que el distintivo sea más confiable
fuente
¿De qué se trata su consulta existente que no le gusta? Si te preocupa que
DISTINCT
en dos columnas no devuelva solo las permutaciones únicas, ¿por qué no probarlo?Ciertamente funciona como es de esperar en Oracle.
editar
Bajé por un callejón sin salida con análisis, pero la respuesta fue deprimentemente obvia ...
editar 2
Teniendo en cuenta los siguientes datos, la solución de concatenación proporcionada anteriormente contará erróneamente:
Entonces incluiremos un separador ...
Obviamente, el separador elegido debe ser un carácter, o conjunto de caracteres, que nunca puede aparecer en ninguna columna.
fuente
Para ejecutar como una sola consulta, concatene las columnas, luego obtenga el recuento distinto de instancias de la cadena concatenada.
En MySQL puede hacer lo mismo sin el paso de concatenación de la siguiente manera:
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
fuente
SELECT COUNT(DISTINCT (DocumentId, DocumentSessionId)) FROM DocumentOutputItems;
¿Qué tal algo como:
Probablemente solo haga lo mismo que usted, pero evita el DISTINCT.
fuente
GROUP BY
puede presentar un par de desafíos adicionales a la transformación de la consulta para lograr el resultado deseado (por ejemplo, cuando la consulta original ya teníaGROUP BY
oHAVING
cláusulas ...)Aquí hay una versión más corta sin la subselección:
Funciona bien en MySQL, y creo que al optimizador le resulta más fácil entenderlo.
Editar: Aparentemente leí mal MSSQL y MySQL, lo siento, pero tal vez ayude de todos modos.
fuente
count ( distinct CHECKSUM ([Field1], [Field2])
Muchas (¿la mayoría?) Bases de datos SQL pueden funcionar con tuplas como valores, por lo que puede hacer lo siguiente:
SELECT COUNT(DISTINCT (DocumentId, DocumentSessionId)) FROM DocumentOutputItems;
si su base de datos no lo admite, puede simularse según la sugerencia de @ oncel-umut-turer de CHECKSUM u otra función escalar que brinde una buena singularidad. por ejCOUNT(DISTINCT CONCAT(DocumentId, ':', DocumentSessionId))
.Un uso relacionado de tuplas es realizar
IN
consultas como:SELECT * FROM DocumentOutputItems WHERE (DocumentId, DocumentSessionId) in (('a', '1'), ('b', '2'));
fuente
select count(distinct(a, b))
? : DNo hay nada malo con su consulta, pero también puede hacerlo de esta manera:
fuente
Espero que esto funcione, estoy escribiendo en prima vista
fuente
He usado este enfoque y me ha funcionado.
Para mi caso, proporciona el resultado correcto.
fuente
si solo tuviera un campo para "DISTINCT", podría usar:
y eso devuelve el mismo plan de consulta que el original, según lo probado con SET SHOWPLAN_ALL ON. Sin embargo, está utilizando dos campos para que pueda probar algo loco como:
pero tendrá problemas si hay NULL involucrados. Solo me quedaría con la consulta original.
fuente
Encontré esto cuando busqué en Google mi propio problema, descubrí que si cuentas los objetos DISTINCT, obtienes el número correcto devuelto (estoy usando MySQL)
fuente
DocumentId
yDocumentSessionId
). Alexander Kjäll ya publicó la respuesta correcta si el OP estaba usando MySQL y no MS SQL Server.Desearía que 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, pero después 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é un poco y descubrí que Microsoft NO recomienda usar CHECKSUM para fines de detección de cambios. En algunos foros algunos sugirieron usar
pero esto tampoco es reconfortante.
Puede usar la función HASHBYTES () como se sugiere en el enigma CHECKSUM de TSQL . Sin embargo, esto también tiene una pequeña posibilidad de no devolver resultados únicos.
Sugeriría usar
fuente
Qué tal esto,
Esto nos dará el recuento de todas las combinaciones posibles de DocumentId y DocumentSessionId
fuente
Esto funciona para mi. En oráculo:
En jpql:
fuente
Tenía una pregunta similar, pero la consulta que tuve fue una subconsulta con los datos de comparación en la consulta principal. algo como:
Ignorando las complejidades de esto, me di cuenta de que no podía obtener el valor de un código en la subconsulta con la subconsulta doble descrita en la pregunta original
Así que eventualmente descubrí que podía hacer trampa y combinar las columnas:
Esto es lo que terminó funcionando
fuente
Si está trabajando con tipos de datos de longitud fija, puede enviarlos
binary
para hacerlo de manera muy fácil y rápida. AsumiendoDocumentId
yDocumentSessionId
son ambosint
s, y por lo tanto son 4 bytes de longitud ...Mi problema específico me obligaba a dividir un
SUM
porCOUNT
combinación distinta de varias claves foráneas y un campo de fecha, agrupando por otra clave foránea y ocasionalmente filtrando por ciertos valores o claves. La tabla es muy grande y el uso de una subconsulta aumentó drásticamente el tiempo de consulta. Y debido a la complejidad, las estadísticas simplemente no eran una opción viable. LaCHECKSUM
solución también fue demasiado lenta en su conversión, particularmente como resultado de los diversos tipos de datos, y no podía arriesgar su falta de confiabilidad.Sin embargo, el uso de la solución anterior prácticamente no aumentó el tiempo de consulta (en comparación con el uso de simplemente el
SUM
), ¡y debería ser completamente confiable! Debería poder ayudar a otros en una situación similar, así que lo estoy publicando aquí.fuente
Simplemente puede usar la función Count dos veces.
En este caso, sería:
fuente
Este código utiliza distintos parámetros en 2 y proporciona el recuento de la cantidad de filas específicas para esos valores distintos. Me funcionó en MySQL como un encanto.
fuente