2009-10-21 15 views
10

Tengo 2 tablas. Una es una mesa con cosas que se pueden aprender. Hay un JID que describe cada tipo de fila, y es único para cada fila. La segunda tabla es un registro de las cosas que se han aprendido (el JID) y también el ID de usuario de la persona que lo aprendió. Actualmente estoy usando esto para seleccionar todos los datos para el JID, pero solo los que el usuario ha aprendido en función del ID de usuario.Seleccione * de la tabla 1 que no existe en la tabla 2 con condicional

SELECT * 
FROM tablelist1 
LEFT JOIN tablelog2 ON (tablelist1.JID = tablelog2.JID) 
         AND tablelog2.UID = 'php var' 
WHERE tablelog2.JID IS NOT NULL 

Ahora necesito seleccionar las filas de cosas para aprender, pero solo las cosas que el ID de usuario NO ha aprendido. Obviamente soy muy nuevo en esto, tengan paciencia conmigo. :) Intenté usar IS NULL, pero aunque parece funcionar, da como resultado que el JID duplicado sea NULL, siendo uno correcto.

Respuesta

16

Usando LEFT JOIN/IS NULL:

SELECT t.* 
    FROM TABLE_LIST t 
LEFT JOIN TABLE_LOG tl ON tl.jid = t.jid 
    WHERE tl.jid IS NULL 

Usando NO EN:

SELECT t.* 
    FROM TABLE_LIST t 
WHERE t.jid NOT IN (SELECT tl.jid 
         FROM TABLE_LOG tl 
        GROUP BY tl.jid) 

Usando NO EXISTE:

SELECT t.* 
    FROM TABLE_LIST t 
WHERE NOT EXISTS(SELECT NULL 
        FROM TABLE_LOG tl 
        WHERE tl.jid = t.jid) 

FYI
combinación izquierda/IS NULL y NOT IN son equivalentes en MySQL - w realizará lo mismo, mientras que NOT EXISTS es más lento/menos eficiente. Para más detalles: http://explainextended.com/2009/09/18/not-in-vs-not-exists-vs-left-join-is-null-mysql/

+0

¿Es posible hacer w/o el uso de subconsultas? las subconsultas son muy lentas, y la tabla 2 tendrá MUCHAS filas. De la misma manera que usé una unión en cambio inicialmente. – user192738

+1

Left Join funcionó perfecto. Gracias por el FYI. No sabía que NOT IN era igual, ¡aunque parece que la selección extra lo desaceleraría! – user192738

3

En primer lugar, usted debe utilizar un INNER JOIN en la consulta existente:

SELECT * FROM tablelist1 
    INNER JOIN tablelog2 ON (tablelist1.JID = tablelog2.JID) 
    WHERE tablelog2.UID = 'php var' 

La forma en que lo está haciendo usted está recibiendo todas las filas de tablelist1, a continuación, ir a problemas adicionales para excluir a los que no tienen una coincidencia en tablelog2. INNER JOIN lo hará por usted y de manera más eficiente.

En segundo lugar, para encontrar para el usuario "X" todas las cosas que se pueden aprender-que el usuario no ha aprendido, hacer:

SELECT * FROM tablelist1 
    WHERE NOT EXISTS (SELECT JID FROM tablelog2 WHERE UID = 'X') 
+0

Voy a probar la primera sugerencia. el segundo (no existe) es más fácil, pero es más lento y es algo que me gustaría evitar ya que t2log podría tener muchos registros. – user192738

+0

El tiempo de ejecución del segundo comando dependerá principalmente del tamaño de tablelist1 y del número de registros que coincidan con UID = 'X' en tablelog2. Tenga en cuenta que la subconsulta no está correlacionada con la parte principal de la consulta y solo tendrá que ejecutarse una vez y es fácilmente manejada por un índice de cobertura, si existe para UID, JID. –

+0

PD: ¿Quiere decir que SABE que el segundo comando es demasiado lento, o PIENSA que será porque leyó en algún lugar para evitar ese tipo de construcción? Pruébelo primero, a menos que haya una gran cantidad de cosas aprendidas para UID "X", debería ser bastante rápido. –

Cuestiones relacionadas