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.

Foi útil?

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
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top