2009-07-20 15 views
5

Prendi ad esempio un'applicazione che ha utenti, ognuno dei quali può trovarsi esattamente in un gruppo. Se vogliamo SELEZIONARE l'elenco di gruppi che non hanno membri, quale sarebbe l'SQL corretto? Continuo a sentirmi come se stessi per cogliere la domanda, e poi scompare di nuovo.Seleziona tutti gli elementi in una tabella che non appaiono in una chiave esterna di un'altra tabella

Punti bonus - dato il senario alternativo, dove è un accoppiamento molti a molti, qual è l'SQL per identificare i gruppi inutilizzati?

(se si desidera che i nomi dei campi in cemento :) uno-a-molti:

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

molti-a-molti:

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

Grazie per entrambe le risposte, entrambi funzionano. Sono curioso di sapere se c'è qualche differenza funzionale tra i due metodi. – dimo414

+0

@ dimo414 - almeno in Sql Server (2005), il piano di esecuzione per la mia versione è più breve e ha un costo * marginalmente * inferiore. In realtà, sarebbe da considerarsi più leggibile, a meno che non si stiano utilizzando enormi set di dati! =) – Rob

+0

Tuttavia, avendo appena eseguito entrambe le query nello stesso batch con 65.536 righe in users_groups, la mia query arriva all'1% del costo in lotti e un'altra a 99% del batch, entrambi eseguiti in meno di un secondo in totale però – Rob

risposta

4

gruppi che non hanno membri (per i molti-molti pairing):

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

Questo Sql funziona anche nel tuo esempio "prima", come si può sostituire "utenti" per "users_groups" nel sub-query =)

quanto riguarda le prestazioni è interessato, io so che questa domanda può essere molto performante su SQL Server, ma io non sono così sicuro come MySql piace ..

2

Per il primo, provate questo:

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

Per il secondo, prova questo:

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 
) 

Tornerà Tutti gli ID di gruppo che non sono presenti nell'utente

Problemi correlati