2009-09-19 9 views
3

structures de tableau simplifié, toutes les INT colonnes et pas PKs en dehors des colonnes d'identité:Sélection de lignes d'identité distinctes en fonction de la valeur la plus basse d'une colonne prioritaire rejoint

noeuds (n) Tableau: id

Attributs (a) tableau: id, node_id, type_id

type (t) tableau:J'essaie de sélectionner un ensemble d'attributs, dont chacun a la plus faible priorité de type pour son nœud respectif. Bien qu'il existe plusieurs attributs par node_id, je veux seulement choisir celui avec la plus faible valeur de priorité:

a1 n1 t1 p0 * 
a2 n1 t2 p1 
a3 n2 t2 p1 * 
a4 n2 t3 p2 

Ceci est la requête de base que je travaille à partir, à quel point je suis aussi être coincé:

SELECT * 
    FROM a 
LEFT JOIN t ON a.type_id = t.id 
GROUP BY node_id 

Ma première pensée était d'utiliser un agrégat, MIN, mais je suis alors des problèmes correspondant à la priorité la plus basse pour une node_id avec l'attribut correct.

+0

@Stiggler: Que signifie "implicitement sélectionné" pour vous? –

+0

@Stiggler: Un attribut peut-il être associé à un ou plusieurs node_id? Si oui, cela signifie qu'il y aura deux listes d'attributs avec des priorités les plus basses (éventuellement différentes) pour autant de noeuds (en supposant que ATTRIBUTES.type_id ne peut pas être nul). –

Répondre

2

Cette question est une variante du problème « le plus grand-n-par-groupe », mais vous cherchez le moins au lieu de Le plus grand, et vos critères sont dans une table de recherche (Type) au lieu de la table principale (Attributes).

Vous souhaitez donc que les lignes() de Attributes de sorte qu'aucune autre ligne avec le même node_id est associée à une priorité inférieure.

SELECT a1.* 
FROM Attributes a1 INNER JOIN Type t1 ON (a1.type_id = t1.id) 
LEFT OUTER JOIN (
    (Attributes a2 INNER JOIN Type t2 ON (a2.type_id = t2.id)) 
    ON (a1.node_id = a2.node_id AND t1.priority > t2.priority) 
WHERE a2.node_id IS NULL; 

Notez que cela peut entraîner des liens. Vous n'avez pas décrit comment résoudre les liens si deux Attributs référencent des Types avec la même priorité. En d'autres termes, dans les exemples suivants, quels attributs doivent être sélectionnés?

a1 n1 t1 p0 
a2 n1 t1 p0 
a3 n2 t2 p1 
a4 n2 t3 p1 

PS: J'espère que ça ne te dérange pas que j'ajouté le tag "plus grand-n-par-groupe" à votre question. Cliquez sur ce tag pour voir les autres questions sur le SO que j'ai tagué de la même manière.

+0

Merci Bill, c'était exactement ce que je cherchais! J'ai pensé que ce problème particulier avait un nom, mais je ne pouvais pas comprendre ce que c'était. En utilisant votre exemple de requête, j'ai construit une requête qui semble sélectionner exactement ce que je veux (mes tables réelles sont plus complexes que celles que j'ai fournies). Votre observation sur les liens est également correcte. Heureusement, ce n'est pas une faute de conception, mais quelque chose que je prévois d'empêcher, même si je ne l'ai pas encore fait.Pour l'instant, choisir l'une des rangées attachées suffira. – Stiggler

+1

Ok, super je suis content de pouvoir aider. Juste pour que vous sachiez, cette solution renvoie * les deux * lignes dans les cas où il y a des liens. –

2

Utiliser requête tie-breaker (non testé):

SELECT  n.*, a.* 
FROM  Nodes n 
LEFT JOIN Attributes a 
     ON a.id = (SELECT  x.id --//TOP 1 x.id 
        FROM  Attributes x 
        INNER JOIN Type t 
          ON x.type_id = t.id 
        WHERE  x.node_id = n.id 
        ORDER BY t.priority ASC, 
           --//just in case there are 2 attributes 
           --//with the same priority, order also on x.id 
           x.id ASC 
        LIMIT 1 
        ) 
+1

@Van: Ceci est MySQL - ne devrait pas "' TOP 1' "être" 'LIMIT 1'"? –

+0

@rexem: merci, changé - j'espère que c'est correct – van

Questions connexes