2011-12-08 21 views
24

Ok, entonces tengo una tabla temporal que contiene el ID de usuario y el ID de tarea. Se llama CompletedTasks. Tengo una segunda tabla que contiene ID de usuario e ID de tarea. Se llama Tareas planificadas.mysql "Where not in" usando dos columnas

Necesito obtener una lista de todos los ID de tareas que se completaron, pero no se planificaron. Por lo tanto, necesito eliminar de alguna manera las tareas completadas en todas las filas donde ambos PlannedTasks.userID != CompletedTasks.userID AND PlannedTasks.taskID != CompletedTasks.taskID.

Espero que esta pregunta tenga sentido. Por favor, avíseme si no está claro y explicaré más a fondo.

¡Gracias por cualquier consejo!

+0

Creo que necesita una columna adicional para indicar el estado, realmente no necesita dos tablas. – ajreal

+0

@ajreal Ese es un buen punto. Tal vez considere modificar el esquema de la manera que sugirió. ¡Aprecia el consejo! – PFranchise

+1

Prefiero 2 tablas sobre una tabla y una columna de estado, el 99% del tiempo. Y 11 tablas sobre una tabla y 10 columnas de estado. No es fácil optimizar una consulta que busca una o varias columnas de estado (en MysQL). –

Respuesta

62

Puede utilizar esta (más de sintaxis compacta):

SELECT * 
FROM CompletedTasks 
WHERE (userID, taskID) NOT IN 
     (SELECT userID, taskID 
     FROM PlannedTasks 
    ) ; 

o la versión NOT EXISTS (que aunque más compleja, debe ser más eficientes con índices adecuados):

SELECT c.* 
FROM CompletedTasks AS c 
WHERE NOT EXISTS 
     (SELECT 1 
     FROM PlannedTasks AS p 
     WHERE p.userID = c.userID 
      AND p.taskID = c.taskID 
    ) ; 

y por supuesto la versión LEFT JOIN/IS NULL que @jmacinnes tiene en su respuesta.

+0

¡Impresionante! Muchas gracias. No sabía que podrías usar Where en dos campos de esa manera, pero tenía la esperanza de que esa fuera una opción. Gracias de nuevo y ten un buen día! – PFranchise

+0

Después de mis pruebas, la versión NOT EXISTS es más rápida que la versión NOT_IN –

+0

@Ka. sí, el 'NOT IN' con una tupla no está optimizado y 'NOT EXISTS'. ¿Con qué versión pruebaste? No he probado si han mejorado el optimizador en la nueva versión 5.7. –

5

¿Es esto lo que necesita?

select ct.* from 
completedTasks ct 
left outer join plannedTasks pt on ct.taskId = pt.TaskId and ct.userId = pt.userId 
where pt.taskId is null 

Sin embargo, estoy de acuerdo con el comentario - dado lo que sabemos de la cuestión de una columna de estado suena como un mejor esquema de dos tablas.

0

@ ypercubeᵀᴹ Gracias por compartir a continuación consulta mención

SELECT * FROM CompletedTasks WHERE (userID, taskID) NOT IN 
     (SELECT userID, taskID FROM PlannedTasks) ;' 

Mi problema resuelto.

+0

Esto debería ser un comentario, no una respuesta :) – sniperd

+0

En realidad, hice algunos cambios con referencia a @ypercube consulta compartida. Cuidará en el futuro. Gracias –

Cuestiones relacionadas