2010-07-02 7 views
5

J'utilise SQL Server 2008 et j'ai 3 tables, x, y et z. y existe pour créer une relation many-to-many entre x et z. Toutes les zones ci-dessus sont int.Valeur maximale dans une relation plusieurs-à-plusieurs

Je veux trouver la méthode la plus performante (à l'exception dénormaliser) de trouver le z avec le plus haut sort pour tout x et retourner tous les champs de trois tables.

données Exemple:

x: id 
    -- 
     1 
     2 

y: xid zid 
    --- --- 
     1 1 
     1 2 
     1 3 
     2 2 

z: id sort 
    -- ---- 
    1 5 
    2 10 
    3 25 

Le jeu de résultats doit être

xid zid 
--- --- 
    1 3 
    2 2 

Notez que si plus d'un z existe avec la même valeur la plus élevée sort, alors je veux toujours une seule ligne par x.

Notez également que dans ma situation réelle, il y a d'autres champs dans les trois tables dont j'ai besoin dans mon jeu de résultats.

+0

Je suppose que vous êtes après que la solution de la situation réelle du monde? Je vous suggère de mettre à jour votre question avec quelques champs supplémentaires pour chaque table, et de définir ce que vous souhaitez que votre ensemble de résultats à rechercher. – MPritchard

+0

Juste pour ajouter à cette question. La conception de votre base de données est-elle corrigée ou en cours de mise en œuvre? Je trouve étrange que votre "sort" soit dans la table z et non dans la table y. Je trouve habituellement qu'une relation de plusieurs à plusieurs comme celle-ci a souvent le genre pour lequel "z" vous pourriez être intéressé par la table "y". Ignorez-moi si je me trompe, il est impossible de savoir sans contexte. –

+0

Il est toujours en cours d'implémentation et je suis d'accord avec ce que vous dites, mais dans le contexte de ce qui est en cours de construction, le tri est et devrait être sur la table 'z'. – enashnash

Répondre

0

Une méthode est avec une sous-requête. Cependant, cela n'est bon que pour obtenir l'ID de Z. Si vous avez besoin de plus/toutes les colonnes des tables x et z, alors ce n'est pas la meilleure solution.

SELECT 
    x.id, 
    (
     SELECT TOP 1 
      z.zid 
     FROM 
      y 
     INNER JOIN 
      z 
     ON 
      z.id = y.zid 
     WHERE 
      y.xid = x.id 
     ORDER BY 
      z.sort DESC 
    ) 
FROM 
    x 

Voici comment vous pouvez le faire et renvoyer toutes les données de toutes les tables.

SELECT 
    * 
FROM 
    x 
INNER JOIN 
    y 
ON 
    y.xid = x.id 
AND 
    y.zid = 
(
    SELECT TOP 1 
     z2.zid 
    FROM 
     y y2 
    INNER JOIN 
     z z2 
    ON 
     z2.id = y2.zid 
    WHERE 
     y2.xid = x.id 
    ORDER BY 
     z2.sort DESC 
) 
INNER JOIN 
    z 
ON 
    z.id = y.zid 
+0

clarifié en question – enashnash

+0

édité pour inclure toutes les données –

+0

Je viens de comparer cela avec la solution fournie par arachnid et il est sorti 8% plus rapide en contexte pour moi. – enashnash

0
select xid,max(zid) as zid from y 
group by xid 
+0

le max est censé être sur "trier" pas sur zid. donc cela ne fonctionne pas –

0
select xid, zid /* columns from x; and columns from y or z taken from q */ 
from (select y.xid, y.zid, /* columns from y or z */ 
      row_number() over(partition by y.xid order by z.sort desc) r 
     from y 
      join z on z.id = y.zid 
    ) q 
    join x on x.id = q.xid 
where r = 1 
+0

Je pense que c'est ce que je cherche. Je peux ajouter des colonnes supplémentaires à la sélection interne, puis en sélectionner une dans la fenêtre externe pour obtenir toutes les colonnes des trois tables. Maintenant, j'ai juste besoin de savoir si c'est la façon la plus performante de le faire. – enashnash

Questions connexes