2009-07-20 6 views
5

Prenons par exemple une application qui a des utilisateurs, chacun d'eux pouvant faire partie d'un groupe. Si nous voulons SELECT la liste des groupes qui n'ont pas de membres, quel serait le bon SQL? Je continue à me sentir comme si je suis sur le point de saisir la requête, puis il disparaît à nouveau.Sélectionnez tous les éléments d'une table qui n'apparaissent pas dans une clé étrangère d'une autre table

Points bonus - étant donné l'alternative senario, où il s'agit d'un appariement de plusieurs à plusieurs, quel est le code SQL pour identifier les groupes inutilisés?

(si vous voulez que les noms concrets sur le terrain :) One-To-Many:

Table 'users': | user_id | group_id | 
Table 'groups': | group_id | 

Many-to-Many:

Table 'users': | user_id | 
Table 'groups': | group_id | 
Table 'user-group': | user_id | group_id | 
+0

Merci pour les deux réponses, ils fonctionnent tous les deux. Je suis curieux de savoir s'il y a une différence fonctionnelle entre les deux méthodes. – dimo414

+0

@ dimo414 - au moins dans Sql Server (2005), le plan d'exécution de ma version est plus court et a un coût * légèrement inférieur. Vraiment, ce serait à celui que vous considérez plus lisible, sauf si vous utilisez des jeux de données massifs! =) – Rob

+0

Cependant - après avoir exécuté les deux requêtes dans le même lot avec 65.536 lignes dans users_groups, ma requête arrive à 1% du coût du lot et une autre à 99% du lot - les deux sont toujours exécutées en moins d'un deuxième au total si – Rob

Répondre

4

groupes qui ont pas de membres (pour les nombreux-many appariement):

SELECT * 
FROM groups g 
WHERE NOT EXISTS 
    (
     SELECT 1 
     FROM users_groups ug 
     WHERE g.groupid = ug.groupid 
    ); 

Cette Sql travaillera également dans votre exemple « d'abord » comme vous pouvez le remplacer par « utilisateurs » pour « users_groups » dans le sous-requête =)

en ce qui concerne la performance est, je sais que cette requête peut être très performant sur Sql Server, mais je ne suis pas sûr de savoir comment MySql aime ..

2

Pour le premier, essayez ceci:

SELECT * FROM groups 
LEFT JOIN users ON (groups.group_id=users.group_id) 
WHERE users.user_id IS NULL; 

Pour le second, essayez ceci:

SELECT * FROM groups 
LEFT JOIN user-group ON (groups.group_id=user-group.group_id) 
WHERE user-group.user_id IS NULL; 
1
SELECT * 
FROM groups 
WHERE groups.id NOT IN (
    SELECT user.group_id 
    FROM user 
) 

Il reviendra n tous les id de groupe qui ne sont pas présents dans l'utilisateur

Questions connexes