2009-06-10 16 views
5

Tengo tres tablas:unirse a una mesa varias veces para otras tablas

la tabla de usuario (nombre de usuario ID de usuario)

tabla de claves (keyid identificador de usuario)

la tabla del ordenador (laptopid identificador de usuario)

Quiero todos los usuarios que tienen una clave o una computadora portátil, o ambos. ¿Cómo escribo la consulta para que utilice una unión entre la tabla de usuario y la clave de tabla, así como también una combinación entre la tabla Usuario y la tabla portátil?

El principal problema es que en el escenario actual, hay doce o más uniones de tablas, algo así como:

"seleccionar .. De una izquierda unirse b en (...), C unirse a d en (..), e, f, g donde ... ",

y veo que a se puede unir a b, y a también se puede unir a f. Entonces, suponiendo que no puedo hacer que las tablas a, b y f aparezcan una al lado de la otra, ¿cómo escribo la consulta sql?

+0

Todos los usuarios deben tener la llave o la computadora portátil. ¿Derecha? –

+0

puede que tengas razón, podría estar equivocado, ¡pero no te importa! aún así es divertido :) – umar

+0

Q1: ¿quieres saber solo el usuario (ID de usuario) o también qué tenían exactamente? Q2: ¿Puede un usuario tener más de un elemento de un tipo (2 computadoras portátiles o 3 teclas)? – van

Respuesta

1
select distinct u.userid, u.username 
from User u 
    left outer join Key  /* k on u.userid = k.userid */ 
    left outer join Laptop /* l on u.userid = l.userid */ 
where k.userid is not null or l.userid is not null 

EDITAR "El principal problema es que en el escenario actual, hay doce o más uniones de tablas, algo así como: " seleccionar .. De una izquierda unirse b en (...) , c join d on (..), e, f, g donde ... ", y veo que a se puede unir a b, y a también se puede unir a f. Suponiendo que no puedo hacer las tablas a, b yf aparecen una al lado de la otra, ¿cómo escribo la consulta sql? "

Puede tener tantas juntas externas izquierdas como sea necesario. Únase a la tabla con la clave principal para el resto de las tablas o en cualquier otro campo donde los valores de campo de una tabla deben coincidir con los valores de campo de otra tabla.

por ejemplo explicará mejor que las palabras

select * 
from a 
left outer join b on a.pk = b.fk -- a pk should match b fk 
left outer join c on a.pk = c.fk -- a pk should match c fk 
left outer join d on c.pk = d.fk -- c pk should match d fk 

y así sucesivamente

+0

completé la pregunta para mostrar mi principal dificultad no es ser capaz de hacer que las tres tablas aparecen al lado del otro, con algo como tabla completa se une a (i decir: "de C, D", etc.) que aparecen mezclados entre – umar

+0

ans editada como por ur editado Q –

+1

Todavía omite una cláusula where como "donde k.userid no es nulo o l.userid no es nulo" en su primera respuesta para filtrar a los usuarios sin nada. –

9

Puede utilizar varias combinaciones de combinar varias tablas:

select * 
from user u 
left join key k on u.userid = k.userid 
left join laptop l on l.userid = u.userid 

Una "combinación izquierda" también encuentra los usuarios, que no tiene una llave o una computadora portátil. Si reemplaza ambos con "unión interna", encontrará solo usuarios con una computadora portátil y una clave.

Cuando una "combinación izquierda" no encuentra una fila, devolverá NULO en sus campos. Así que usted puede seleccionar todos los usuarios que tienen ya sea un ordenador portátil o una tecla de la siguiente manera:

select * 
from user u 
left join key k on u.userid = k.userid 
left join laptop l on l.userid = u.userid 
where k.userid is not null or l.userid is not null 

NULL es especial, en el que se compara como "campo no es nulo" en lugar de "campo <> nula".

Alta después de su comentario: supongamos que tiene una mesa de ratón, que se relaciona con el ordenador portátil, pero no al usuario. Puede unirse a eso como:

select * 
from user u 
left join laptop l on l.userid = u.userid 
left join mouse m on m.laptopid = l.laptopid 

Si esto no responde a su pregunta, debe aclararlo un poco más.

+0

Creo que el último u.userid debería ser k.userid –

+0

¡sí! Es la respuesta correcta como mi respuesta. +1 –

+0

disculpa por no aclarar la pregunta anterior: he agregado más detalles a la pregunta para que tu respuesta aparentemente no resuelva mi problema – umar

1

Como se describió el caso, sólo quería saber si alguien tiene un ordenador portátil o una llave.Yo escribo la consulta con una subconsulta en lugar de una combinación:

select * 
from user 
where userid in (select userid from key union select userid from laptop) 

La razón de esto es que se unen por una persona con múltiples ordenadores portátiles o varias claves serán mencionados varias veces (a menos que utilice distinct). E incluso si usas distinct terminas con una consulta menos eficiente (al menos en Oracle el optimizador de consultas no parece ser capaz de crear un plan eficiente).

+1

No será una combinación cruzada si especificas la combinación externa izquierda. La combinación externa izquierda es más rápida que la subconsulta. –

+0

Lo probé rápidamente en una base de datos Oracle: tiene razón, no causa una unión cruzada. Pero tampoco fue más rápido que el método de subconsulta, en realidad más del doble de lento. – waxwing

+0

Quiero hacer muy pocas modificaciones a la consulta excepto agregar más cláusulas JOIN y ON, por lo que estoy buscando una forma de hacerlo sin usar subconsultas. También he base de datos MySQL cuyo comportamiento puede ser diferente de la conducta oráculos en consultas anidadas – umar

0
SELECT * 
FROM User 
LEFT JOIN Key ON User.id = Key.user_id 
LEFT JOIN Laptop ON User.id = Laptop.user_id 
WHERE Key.id IS NOT NULL OR Laptop.id IS NOT NULL 
0

solución todo en uno [Editado para corregir lo Rashmi Pandit señaló.]:

SELECT * FROM [User] u 
INNER JOIN [Key] k 
ON u.userid = k.userid 

UNION 

SELECT * FROM [User] u 
INNER JOIN Laptop l 
ON u.userid = l.userid 

[...] 

Solución dos:

SELECT * FROM [User] u 
LEFT JOIN [Key] k 
ON u.userid = k.userid 
LEFT JOIN Laptop l 
ON u.userid = l.userid 
LEFT JOIN [...] 
WHERE k.userid IS NOT NULL 
OR l.userid IS NOT NULL 
OR [...] 

Sólo una conjetura, también se puede comprobar el plan de ejecución de estos dos para ver si UNION uno es más pesado o viceversa.

2
-- // Assuming that a user can have at max 1 items of each type 
SELECT  u.* 
-- // Assuming that a user can have more then 1 items of each type, just add DISTINCT: 
-- // SELECT  DISTINCT u.* 
FROM  "User" u 
LEFT JOIN "Key" u1 ON u.UserID = u1.UserID 
LEFT JOIN "Laptop" u2 ON u.UserID = u2.UserID 
LEFT JOIN "Server" u3 ON u.UserID = u3.UserID 
-- // ... 
WHERE  COALESCE(u1.UserID, u2.UserID, u3.UserID /*,...*/) IS NOT NULL 
+0

+1 uso interesante de fusión} – Andomar

Cuestiones relacionadas