2010-09-23 20 views
16

Tengo tres tablas: R, S y P.SQL unir tres tablas, unir a la precedencia

Tabla R Se une con S a través de una clave externa; no debería ser al menos un registro en S, por lo que pueden unirse a:

SELECT 
     * 
    FROM 
     R 
    JOIN S ON (S.id = R.fks) 

Si no hay ningún registro en S entonces consigo ninguna fila, eso está bien.

Entonces mesa S se une con P, donde P es registros pueden o pueden no estar presentes y se unieron con S.

Así que hago

SELECT 
     * 
    FROM 
     R 
    JOIN S ON (S.id = R.fks) 
    LEFT JOIN P ON (P.id = S.fkp) 

¿Qué pasa si yo quería que el segundo se unen para ser atado a S no a R, como si pudiera utilizar paréntesis:

SELECT 
     * 
    FROM 
     R 
    JOIN (S ON (S.id = R.fks) JOIN P ON (P.id = S.fkp)) 

O es que ya es un comportamiento natural del producto cartesiano entre R, S y P?

+0

¿Puede explicar esta parte "¿Qué pasa si yo quería que el segundo se unen para ser atado a S no a R" En este momento las tablas se combinan como R unirse con S y luego a la izquierda unirse con P. –

+0

Estoy intentando para entender si hay una manera en que puedo dar prioridad a las uniones, como si fueran operadores aritméticos. No entiendo si esto está implícito en la condición de unión o no. – vulkanino

+0

Dénos un ejemplo de datos de lo que espera lograr que sea diferente de una unión ordinaria y podemos mostrarle mejor qué hacer. Es posible que una tabla derivada haga lo que usted desea, pero no estoy seguro exactamente de lo que quiere. – HLGEM

Respuesta

26

Todos los tipos de uniones externas y normales están en la misma clase de precedencia y los operadores tienen efecto de izquierda a derecha en un nivel de anidamiento dado de la consulta. Puede poner la expresión de unión en el lado derecho entre paréntesis para hacer que surta efecto primero; solo recuerde que debe mover la cláusula ON de la unión que ahora está fuera de la unión en la que ha insertado los parientes.

(PostgreSQL ejemplo)

En SELECT * FROM a LEFT JOIN b ON (a.id = b.id) JOIN c ON (b.ref = c.id);

la ab unirse entra en vigor principio, pero nos puede obligar al bc se unen para entrar en vigor por primera vez por hacer:

SELECT * FROM a LEFT JOIN (b JOIN c ON (b.ref = c.id)) ON (a.id = b.id);

A menudo se puede expresar lo mismo sin paréntesis adicionales moviendo las uniones y cambiando la dirección de unión externa, por ej.

SELECT * FROM b JOIN c ON (b.ref = c.id) RIGHT JOIN a ON (a.id = b.id);

+1

Una aclaración: todos los operadores de unión tienen la misma precedencia y todos tienen asociatividad de izquierda a derecha. Esta es la forma en que los operadores de resta (-) y división (/) trabajan en prácticamente todos los lenguajes de programación. Cambiar el orden de los operandos no tiene ningún efecto sobre su "precedencia" (un aspecto de la gramática de SQL y no el operando en ningún caso). Al hacer esto, se usa la asociatividad de izquierda a derecha de la unión para lograr la semántica deseada de las combinaciones compuestas. Pero no cambia ni la precedencia ni la asociatividad de nada en la expresión, solo su contexto de interpretación. –

+0

Bastante justo. ¿Cuál es una segunda palabra que transmite el efecto de un operador que precede al efecto de otro operador, pero no la precedencia porque eso ya se ha tomado? – rakslice

+0

Reformulado. Además, por mucho que odie pisar la palabra jerga de alguien usándola para su definición de diccionario (no, no), lo que realmente moldea mis engranajes es algo así como "asociatividad", donde la palabra jerga es terminología matemática que se ha apropiado por el mundo de la informática. – rakslice

1

El segundo se unen es atado a S a medida que explícitamente estado JOIN P ON (P.id = S.fkp) - ninguna columna de R se hace referencia en la unión.

+0

bien, pero no hay manera, en general, de dar prioridad a las uniones? – vulkanino

+0

No creo que SQL funcione de la manera en que estás pensando. La respuesta de Paul Spangle describe cómo SQL "piensa" sobre las uniones. –

2

Cuando se une a la tercera tabla, su primera consulta

SELECT 
     * 
    FROM 
     R 
    JOIN S ON (S.id = R.fks) 

es como una tabla derivada a la que se está uniendo a la tercera tabla. Por lo tanto, si R JOIN S no produce filas, al unir P nunca se generarán filas (porque está intentando unirse a una tabla vacía).

Por lo tanto, si está buscando reglas de precedencia, en este caso solo se establece usando LEFT JOIN en contraposición a JOIN.

Sin embargo, es posible que esté malinterpretando su pregunta, porque si estuviera escribiendo la consulta, cambiaría S y R. p.ej.

SELECT 
     * 
    FROM 
     S 
    JOIN R ON (S.id = R.fks) 
+0

considera que tengo que unir 3 tablas, no 2. – vulkanino

+1

Simplemente funciona de izquierda a derecha. La única forma de evitarlo es pensar en poner una tabla derivada completa entre paréntesis. –

1

No hay precedencia para las uniones, es el funcionamiento asociativo. La vieja sintaxis separada por comas lo dejó claro, el nuevo (que presumiblemente se cocina para imitar el álgebra relacional) es confuso. Las uniones externas (usadas solos o juntas con combinaciones regulares), sin embargo, no son asociativas.

+3

Teniendo en cuenta que OP pregunta acerca de LEFT JOINS, la afirmación de que JOINS es asociativa es completamente engañosa. – Taemyr

0
with a as (select 1 as test union select 2) 
select * from a left join 
a as b on a.test=b.test and b.test=1 inner join 
a as c on b.test=c.test 
go 
with a as (select 1 as test union select 2) 
select * from a inner join 
a as b on a.test=b.test right join 
a as c on b.test=c.test and b.test=1 

Idealmente, esperamos que las dos consultas anteriores son los mismos. Sin embargo, no lo son, por lo que cualquier persona que diga que una unión correcta puede ser reemplazada por una combinación izquierda en todos los casos es incorrecta. Solo al usar la combinación correcta podemos obtener el resultado requerido.

+1

, las uniones derechas no tienen nada que ver con esta pregunta y nadie dice que son iguales. – Hogan