Existe uma maneira melhor de fazer uma consulta como esta:
SELECT COUNT(*)
FROM (SELECT DISTINCT DocumentId, DocumentSessionId
FROM DocumentOutputItems) AS internalQuery
Preciso contar o número de itens distintos dessa tabela, mas o distinto tem mais de duas colunas.
Minha consulta funciona bem, mas eu queria saber se posso obter o resultado final usando apenas uma consulta (sem usar uma subconsulta)
sql
sql-server
performance
tsql
query-optimization
Novitzky
fonte
fonte
Respostas:
Se você estiver tentando melhorar o desempenho, tente criar uma coluna computada persistente em um hash ou valor concatenado das duas colunas.
Depois de persistida, desde que a coluna seja determinística e você esteja usando configurações de banco de dados "sãs", ela pode ser indexada e / ou estatísticas podem ser criadas nela.
Acredito que uma contagem distinta da coluna computada seria equivalente à sua consulta.
fonte
Edit: Alterado da consulta somente de soma de verificação menos que confiável, descobri uma maneira de fazer isso (no SQL Server 2005) que funciona muito bem para mim e posso usar quantas colunas forem necessárias (adicionando-as a a função CHECKSUM ()). A função REVERSE () transforma as entradas em varchars para tornar as distintas mais confiáveis
fonte
Do que você não gosta na sua consulta existente? Se você está preocupado que
DISTINCT
duas colunas não retornem apenas as permutações exclusivas, por que não tentar?Certamente funciona como você pode esperar no Oracle.
editar
Desci um beco sem saída com análises, mas a resposta era deprimente óbvia ...
editar 2
Dados os seguintes dados, a solução de concatenação fornecida acima descontará:
Então, vamos incluir um separador ...
Obviamente, o separador escolhido deve ser um caractere ou conjunto de caracteres, que nunca pode aparecer em nenhuma coluna.
fonte
Para executar como uma única consulta, concatene as colunas e obtenha a contagem distinta de instâncias da sequência concatenada.
No MySQL, você pode fazer a mesma coisa sem a etapa de concatenação da seguinte maneira:
Este recurso é mencionado na documentação do MySQL:
http://dev.mysql.com/doc/refman/5.7/en/group-by-functions.html#function_count-distinct
fonte
SELECT COUNT(DISTINCT (DocumentId, DocumentSessionId)) FROM DocumentOutputItems;
Que tal algo como:
Provavelmente, apenas faz o mesmo que você já está, mas evita o DISTINCT.
fonte
GROUP BY
pode introduzir alguns desafios adicionais na transformação da consulta para obter a saída desejada (por exemplo, quando a consulta original já possuiGROUP BY
ouHAVING
cláusulas ...)Aqui está uma versão mais curta sem a subseleção:
Funciona bem no MySQL, e acho que o otimizador tem mais facilidade para entender este.
Edit: Aparentemente, eu li mal o MSSQL e o MySQL - desculpe por isso, mas talvez ajude de qualquer maneira.
fonte
count ( distinct CHECKSUM ([Field1], [Field2])
Muitos bancos de dados SQL (a maioria?) Podem trabalhar com tuplas, como valores, para que você possa fazer isso:
SELECT COUNT(DISTINCT (DocumentId, DocumentSessionId)) FROM DocumentOutputItems;
Se o banco de dados não suportar isso, ele poderá ser simulado conforme a sugestão do CHECKSUM ou de outra função escalar do @ oncel-umuturererer, fornecendo boa exclusividade por exemploCOUNT(DISTINCT CONCAT(DocumentId, ':', DocumentSessionId))
.Um uso relacionado de tuplas está executando
IN
consultas como:SELECT * FROM DocumentOutputItems WHERE (DocumentId, DocumentSessionId) in (('a', '1'), ('b', '2'));
fonte
select count(distinct(a, b))
? : DNão há nada errado com sua consulta, mas você também pode fazer o seguinte:
fonte
Espero que isso funcione, estou escrevendo em prima vista
fonte
Eu usei essa abordagem e funcionou para mim.
Para o meu caso, fornece o resultado correto.
fonte
se você tivesse apenas um campo para "DISTINCT", poderia usar:
e isso retorna o mesmo plano de consulta que o original, testado com SET SHOWPLAN_ALL ON. No entanto, você está usando dois campos para tentar algo louco como:
mas você terá problemas se NULLs estiverem envolvidos. Eu apenas ficaria com a consulta original.
fonte
Encontrei isso quando pesquisei no Google por meu próprio problema, descobri que se você contar objetos DISTINCT, obterá o número correto retornado (estou usando o MySQL)
fonte
DocumentId
eDocumentSessionId
). Alexander Kjäll já postou a resposta correta se o OP estava usando o MySQL e não o MS SQL Server.Gostaria que o MS SQL também pudesse fazer algo como COUNT (DISTINCT A, B). Mas não pode.
No começo, a resposta de JayTee parecia uma solução para mim, depois de alguns testes que CHECKSUM () falhou em criar valores únicos. Um exemplo rápido é que CHECKSUM (31.467.519) e CHECKSUM (69,1120.823) fornecem a mesma resposta, que é 55.
Fiz algumas pesquisas e descobri que a Microsoft NÃO recomenda o uso do CHECKSUM para fins de detecção de alterações. Em alguns fóruns, alguns sugeriram o uso de
mas isso também não é reconfortante.
Você pode usar a função HASHBYTES () conforme sugerido no enigma TSQL CHECKSUM . No entanto, isso também tem uma pequena chance de não retornar resultados exclusivos.
Eu sugeriria usar
fonte
Que tal agora,
Isso nos fornecerá a contagem de todas as combinações possíveis de DocumentId e DocumentSessionId
fonte
Funciona para mim. No oráculo:
No jpql:
fonte
Eu tinha uma pergunta semelhante, mas a consulta que eu tinha era uma subconsulta com os dados de comparação na consulta principal. algo como:
ignorando as complexidades disso, percebi que não era possível obter o valor de a.code na subconsulta com a subconsulta dupla descrita na pergunta original
Então, finalmente, descobri que poderia trapacear e combinar as colunas:
Foi isso que acabou funcionando
fonte
Se você estiver trabalhando com tipos de dados de comprimento fixo, poderá
binary
fazer isso com muita facilidade e rapidez. AssumindoDocumentId
eDocumentSessionId
são ambosint
s e, portanto, têm 4 bytes de comprimento ...Meu problema específico exigia que eu dividisse a
SUM
pelaCOUNT
combinação distinta de várias chaves estrangeiras e um campo de data, agrupando por outra chave estrangeira e ocasionalmente filtrando por determinados valores ou chaves. A tabela é muito grande e o uso de uma subconsulta aumentou drasticamente o tempo de consulta. E devido à complexidade, as estatísticas simplesmente não eram uma opção viável. oCHECKSUM
solução também foi muito lenta na conversão, principalmente como resultado dos vários tipos de dados, e não pude arriscar sua falta de confiabilidade.No entanto, o uso da solução acima praticamente não aumentou o tempo de consulta (em comparação com o simples uso de
SUM
) e deve ser totalmente confiável! Deve ser capaz de ajudar outras pessoas em uma situação semelhante, por isso estou postando aqui.fonte
Você pode apenas usar a função Count duas vezes.
Nesse caso, seria:
fonte
Esse código usa distintos em 2 parâmetros e fornece a contagem do número de linhas específicas para esses valores distintos. Funcionou para mim no MySQL como um encanto.
fonte