2009-07-20 7 views
5

Tomemos por ejemplo una aplicación que tiene usuarios, cada uno de los cuales puede estar en exactamente un grupo. Si queremos SELECCIONAR la lista de grupos que no tienen miembros, ¿cuál sería el SQL correcto? Sigo sintiendo que estoy a punto de captar la consulta, y luego desaparece de nuevo.Seleccione todos los elementos en una tabla que no aparezcan en una clave externa de otra tabla

Puntos de bonificación: dado el senario alternativo, donde hay muchas parejas, ¿qué es SQL para identificar grupos no utilizados?

(si desea que los nombres de campo de hormigón :) uno-a-muchos:

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

Muchos-A-Muchos:

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

Gracias por ambas respuestas, ambas funcionan. Tengo curiosidad si hay alguna diferencia funcional entre los dos métodos. – dimo414

+0

@ dimo414 - al menos en Sql Server (2005), el plan de ejecución para mi versión es más corto y tiene un costo * marginalmente * más bajo. En realidad, sería más abajo de cuál consideras más legible, a menos que estés usando conjuntos de datos masivos. =) – Rob

+0

Sin embargo, habiendo ejecutado ambas consultas en el mismo lote con 65.536 filas en users_groups, mi consulta aparece al 1% del costo del lote y la otra como el 99% del lote, ambas ejecutadas en menos de un segundo en total, aunque – Rob

Respuesta

4

grupos que no tienen miembros (por el mucho-mucho emparejamiento):

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

este SQL también trabajará en su "primera" ejemplo como se puede sustituir "usuarios" para "users_groups" en el sub-consulta =)

en lo que a rendimiento se refiere, sé que esta consulta puede ser muy performante en SQL Server, pero no estoy tan seguro de lo bien que le gusta MySQL ..

2

Para el primero, intentar esto:

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

Para el segundo, intente esto:

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 
) 

Regresará n todo ID de grupo que no está presente en el usuario

Cuestiones relacionadas