2009-09-20 7 views
2

je suit la structure db:Aucune idée comment écrire requête SQL complexe

Fichier, utilisateur, FileRevision (a clé étrangère dans un fichier, et beaucoup-2-many connexion par table intermédiaire à l'utilisateur).

Je veux aller chercher tous les FileRevision-s que:

  1. sont plus récent/plus fraîche dans leur fichier-s correspondant,
  2. ont beaucoup de-2-many lien vers l'utilisateur qui effectue la recherche (vérification des permissions) .

Je trouve que je peux le faire (1) en exécutant quelque chose comme:

SELECT created_on, file_id FROM FileRevision 
WHERE created_on = (SELECT MAX(created_on) FROM FileRevision 
        WHERE filed_id = file_id) 

mais je n'ai pas la moindre idée comment effectuer simultanément aussi m2m la vérification de permission

Répondre

2

Ceci est une variation du problème du "plus grand nombre par groupe". Voilà comment je résous sans sous-requête et pas GROUP BY:

SELECT f1.* 
FROM Permissions p -- this is the many-to-many table 
JOIN FileRevision f1 
    ON (f1.file_id = p.file_id) 
LEFT OUTER JOIN FileRevision f2 
    ON (f2.file_id = p.file_id AND f1.created_on < f2.created_on) 
WHERE p.user_id = ? AND f2.file_id IS NULL; 

Remplacez l'ID d'utilisateur souhaité pour le « ? ».

+0

Cette réponse est ma séquence préférée + JOIN me semble être l'arme puissante pour les recherches complexes. –

1

ajouter ceci à votre requête:

UNION 
SELECT created_on, file_id 
FROM FileRevision fr 
WHERE fr.user_id = ? 

Remplacer? avec n'importe quelle valeur que vous voulez en fonction de votre vérification d'autorisation.

De plus, si vous remplacez votre requête:

SELECT created_on, file_id 
FROM FileRevision fr 
    JOIN 
    (
    SELECT file_id, MAX(created_on) as latestDate 
    FROM FileRevision 
    GROUP BY file_id 
) latest ON latest.file_id = fr.file_id 
      AND latest.latestDate = fr.created_on 

Vous éviterez ainsi la sous-requête en corrélation (répétition).

+0

Merci, je suis allé la plupart du temps avec la solution de Bill Karwin mais cela m'a aussi montré quelques nouvelles astuces SQL. –

1

Pour vérifier les permutations, vous devez vérifier qu'un enregistrement existe dans l'autre table de permissions many-2-many pour l'utilisateur demandant les fichiers. Alors ajoutez une clause And/OR Exists ... Si vous voulez (comme je le soupçonne) seulement la dernière révision à laquelle le demandeur a accès, utilisez AND.

Si vous voulez À la fois la dernière révision et les enregistrements auxquels le demandeur a accès, utilisez OR.

SELECT created_on, file_id 
FROM FileRevision r 
WHERE created_on = 
    (SELECT MAX(created_on) 
    FROM FileRevision      
    WHERE file_id = r.file_id) 
    And Exists  -- Change 'And' to 'Or if you want both 
    (Select * From M2MIntermediatePermissionsTable 
     Where File_Id = r.File_Id 
      And userId = ?) 
+0

Merci, Exists + sélectionnez la table intermédiaire est très utile! –