juntar-se usando DISTINCT interna em SQL
-
03-07-2019 - |
Pergunta
Eu tenho três tabelas, A, B, C, onde A é de muitos para um B e B é de muitos para um C. Eu gostaria de uma lista de todos de C em A.
As minhas tabelas são algo como isto: A [id, valorA, lookupB], B [id, valorB, lookupC], C [id, valorC]. Eu escrevi uma consulta com dois SELECTs aninhadas, mas eu estou querendo saber se é possível fazer INNER JOIN com DISTINCT de alguma forma.
SELECT valueC
FROM C
INNER JOIN
(
SELECT DISTINCT lookupC
FROM B INNER JOIN
(
SELECT DISTINCT lookupB
FROM A
)
A2 ON B.id = A2.lookupB
)
B2 ON C.id = B2.lookupC
EDIT: As tabelas são bastante grandes, A é 500k linhas, B é 10k linhas e C é de 100 linhas, por isso há um monte de informações uneccesary se eu fizer um interior básico juntar e usar DISTINCT no final, como esta:
SELECT DISTINCT valueC
FROM
C INNER JOIN B on C.id = B.lookupB
INNER JOIN A on B.id = A.lookupB
Isto é muito, muito lento (magnitudes vezes mais lento do que o SELECT aninhada faço acima.
Solução
Eu fiz um teste em MS SQL 2005 usando as seguintes tabelas:. Linhas A 400K, linhas B 26K e C 450 linhas
O plano de consulta estimado indicou que o interior básico juntar seria 3 vezes mais lento do que os sub-consultas aninhadas, no entanto, quando realmente executar a consulta, o interior básico junção foi duas vezes mais rápido que as consultas aninhadas, O interior básica junção levou 297ms no hardware do servidor mínimo.
O banco de dados que você está usando, e que horas você está vendo? Estou pensando se você está vendo um desempenho ruim, então provavelmente é um problema de índice.
Outras dicas
Acredito que sua 1:. M relações já deve criar implicitamente DISTINCT JOINs
Mas, se você estiver objetivo é apenas C de em cada uma, pode ser mais fácil simplesmente usar DISTINCT no exterior mais-consulta.
SELECT DISTINCT a.valueA, c.valueC
FROM C
INNER JOIN B ON B.lookupC = C.id
INNER JOIN A ON A.lookupB = B.id
ORDER BY a.valueA, c.valueC
SELECT DISTINCT C.valueC
FROM C
LEFT JOIN B ON C.id = B.lookupC
LEFT JOIN A ON B.id = A.lookupB
WHERE C.id IS NOT NULL
Eu não vejo uma boa razão pela qual você deseja limitar os conjuntos de resultados de A e B porque o que você quer é ter uma lista de todos os de C que são referenciados por A. Eu fiz uma distinta em C.valueC porque imaginei que queria uma lista única de C da.
Editar : Concordo com o seu argumento. Mesmo se a sua solução parece um pouco aninhada parece ser a melhor e mais rápida maneira de usar seu conhecimento dos dados e reduzir os conjuntos de resultados.
Não há distinta juntar-se construir você poderia usar isso só ficar com o que você já tem:)
É isso que você quer dizer?
SELECT DISTINCT C.valueC
FROM
C
INNER JOIN B ON C.id = B.lookupC
INNER JOIN A ON B.id = A.lookupB