Pregunta Usar la combinación interna DISTINCT en SQL


Tengo tres tablas, A, B, C, donde A es de muchos a uno B, y B de muchos a uno C. Me gustaría obtener una lista de todas las C en A.

Mis tablas son algo como esto: A [id, valueA, lookupB], B [id, valueB, lookupC], C [id, valueC]. He escrito una consulta con dos SELECT anidados, pero me pregunto si es posible hacer INNER JOIN con DISTINCT de alguna manera.

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

EDITAR: Las tablas son bastante grandes, A es 500k filas, B es 10k filas y C es 100 filas, por lo que hay mucha información inecesaria si hago una combinación interna básica y uso DISTINCT al final, así:

SELECT DISTINCT valueC
FROM 
C INNER JOIN B on C.id = B.lookupB
INNER JOIN A on B.id = A.lookupB

Esto es muy, muy lento (magnitudes mucho más lentas que el SELECT anidado que hago arriba.


32
2017-10-02 08:48


origen


Respuestas:


Hice una prueba en MS SQL 2005 usando las siguientes tablas: A 400K filas, B 26K filas y C 450 filas.

El plan de consulta estimado indicaba que la combinación interna básica sería 3 veces más lenta que las subconsultas anidadas; sin embargo, cuando se ejecutaba realmente la consulta, la combinación interna básica era dos veces más rápida que las consultas anidadas. La combinación interna básica tardaba 297 ms muy hardware de servidor mínimo.

¿Qué base de datos está usando y qué horarios está viendo? Estoy pensando que si ves un bajo rendimiento, probablemente sea un problema de índice.


13
2017-10-02 13:38



Creo que tu 1: m las relaciones ya deberían crear implícitamente DISTINCT JOINs.

Pero, si su objetivo es solo C en cada A, podría ser más fácil usar DISTINCT en la consulta externa.

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

9
2017-10-02 08:55



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

No veo una buena razón por la que desee limitar los conjuntos de resultados de A y B porque lo que desea es una lista de todas las C a las que hace referencia A. Hice una diferencia en C.valueC porque lo adiviné quería una lista única de C's.


EDITAR: Estoy de acuerdo con tu argumento Incluso si su solución parece un poco anidada, parece ser la mejor y más rápida forma de utilizar su conocimiento de los datos y reducir los conjuntos de resultados.

No existe una construcción de combinación distinta que pueda usar, así que quédese con lo que ya tiene :)


2
2017-10-02 08:55



¿Es esto lo que quieres decir?

SELECT DISTINCT C.valueC
FROM 
C
INNER JOIN B ON C.id = B.lookupC
INNER JOIN A ON B.id = A.lookupB

0
2017-10-02 08:54