Question

J'ai trois tables, A, B, C, où A est plusieurs à un B et B à plusieurs C. Je voudrais une liste de tous les C de A.

Mes tables ressemblent à ceci: A [id, valeurA, lookupB], B [id, valeurB, lookC], C [id, valeurC]. J'ai écrit une requête avec deux SELECTs imbriqués, mais je me demande s'il est possible de faire INNER JOIN avec DISTINCT d'une manière ou d'une autre.

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: Les tables sont assez grandes, A correspond à 500 000 lignes, B à 10 000 lignes et C à 100 lignes. Il existe donc de nombreuses informations inutiles si je fais une jointure interne de base et que j'utilise DISTINCT à la fin, comme ceci:

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

C’est très, très lent (les grandeurs sont plus lentes que le SELECT imbriqué ci-dessus.

Était-ce utile?

La solution

J'ai effectué un test sur MS SQL 2005 à l'aide des tableaux suivants: A 400 Ko lignes, B 26 Ko et C 450 lignes.

Le plan de requête estimé indiquait que la jointure interne de base serait 3 fois plus lente que les sous-requêtes imbriquées. Toutefois, lors de l'exécution de la requête, la jointure interne de base était deux fois plus rapide que les requêtes imbriquées. 297ms sur un serveur très minimal.

Quelle base de données utilisez-vous et à quelle heure le voyez-vous? Je pense que si les performances sont médiocres, il s’agit probablement d’un problème d’index.

Autres conseils

Je pense que vos relations 1: m devraient déjà créer implicitement des jointures DISTINCT.

Toutefois, si votre objectif est uniquement de C dans chaque A, il serait peut-être plus simple d'utiliser DISTINCT dans la requête la plus externe.

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

Je ne vois pas de bonne raison pour laquelle vous souhaitez limiter les résultats de A et B, car vous souhaitez obtenir une liste de tous les C référencés par A. J'ai fait une distinction sur C.valueC car Je suppose que vous vouliez une liste unique de C.

MODIFIER : je suis d'accord avec votre argument. Même si votre solution semble un peu imbriquée, elle semble être le moyen le plus rapide et le plus simple d'utiliser votre connaissance des données et de réduire le nombre de résultats.

Il n’existe pas de structure de jointure distincte que vous pouvez utiliser. Restez donc avec ce que vous avez déjà):

Est-ce ce que vous voulez dire?

SELECT DISTINCT C.valueC
FROM 
C
INNER JOIN B ON C.id = B.lookupC
INNER JOIN A ON B.id = A.lookupB
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top