2011-07-03 16 views
5

Me estoy poniendo viejo o las consultas que necesito para escribir se vuelven cada vez más complicadas. La siguiente consulta obtendrá todos los tasks asociados con el usuario.fusionando dos consultas SELECT

"SELECT `date` 
    FROM `tasks` 
    WHERE `user_id`= 1;" 

La tabla tasks es (id, date, user_id, url_id);

Ahora, tengo que conseguir así los registros que url_id asociados con el usuario A través del

`urls` table (`id`, `user_id`) 

La consulta independiente se vería así:

"SELECT `t1`.`data` 
    FROM `tasks` `t1` 
    JOIN `urls` `u1` ON `u1`.`id` = `t1`.`url_id` 
    WHERE `u1`.user_id` = 1;" 

Sin embargo, es posible fusionar estas dos consultas en una sola consulta? Mi lógica dice que debería ser, aunque no veo cómo hacer la unión real.

+0

¿Quiso decir 'data' or' date' en su última consulta? Además, si no está seleccionando ningún dato de la tabla de URL, ¿realmente necesita unirse a él? (La respuesta podría ser "sí, para asegurarse de que haya una entrada de URL para esa ID de usuario".) Y por qué tantos back-ticks; ¡es tan malo como MS SQL Server y corchetes! –

+0

He escrito la consulta en el camino, por lo que naturalmente dejé algunos errores. Tienes razón, tenía que ser 'date' no' data'. Normalmente ignoraría un comentario sobre 'back-ticks', aunque tiene una reputación bastante alta, así que soy curioso por qué está diciendo que "es tan malo como MS SQL Server y corchetes". El objetivo de los backticks es garantizar que el servidor MySQL pueda identificar rápidamente nombres de tablas y columnas y evitar confusiones al usar palabras clave reservadas, como 'left' o' right' en conjuntos anidados. – Gajus

+0

La misma afirmación se hace para corchetes por usuarios de MS SQL Server. Me parece feo y no es estándar. Ningún otro DBMS admite marcas de retroceso o corchetes para lo que el estándar SQL llama 'identificadores delimitados', que el estándar dice que están entre comillas dobles; las comillas simples están reservadas para las cadenas. Diferentes DBMS tienen diferentes reglas para el uso de palabras clave. El que uso principalmente permite palabras clave como identificadores en muchos lugares. Lo mejor es evitar las comillas evitando las palabras clave como identificadores. –

Respuesta

5

Probablemente usaría un UNION.

SELECT `date` 
    FROM `tasks` WHERE `user_id`=1 
UNION 
SELECT `t1`.`date` 
    FROM `tasks` `t1` 
    INNER JOIN `urls` `u1` ON `u1`.`id` = `t1`.`url_id` 
    WHERE `u1`.user_id`=1; 
+0

Tenga en cuenta que querrá 'UNION ALL' si no desea que se eliminen los duplicados. – tvanfosson

+0

Eso es extraño. Nunca antes había usado UNION en mi vida y esta es la tercera vez en los últimos dos días. :) Sin embargo, ¡gracias! – Gajus

+0

@Guy - de nada, pero me pregunto por qué no votó a favor. :-( – tvanfosson

1

Usted puede hacer esto en una sola consulta:

SELECT t.date 
    FROM TASKS t 
WHERE t.user_id = 1 
    OR EXISTS(SELECT NULL 
       FROM URLS u 
       WHERE u.id = t.url_id 
       AND u.user_id = 1) 

Sin embargo, OR es un intérprete muy malos - astillas que el plan de ejecución. La división de la consulta, uniéndose a los conjuntos de resultados se puede hacer usando los operadores UNION o UNION ALL. UNION elimina duplicados del conjunto de resultados final; UNION ALL no elimina duplicados y es más rápido para ello.

SELECT t.date 
    FROM TASKS t 
WHERE t.user_id = 1 
UNION ALL 
SELECT t.date 
    FROM TASKS t 
WHERE EXISTS(SELECT NULL 
       FROM URLS u 
       WHERE u.id = t.url_id 
       AND u.user_id = 1) 

desconoce sus datos, para que sepa lo que UNION operador sirve mejor a sus necesidades.