unir tablas horizontalmente ejemplos ejemplo consultas consulta concatenar postgresql

postgresql - tablas - unir consultas horizontalmente sql



Unión interna y unión externa; ¿Es importante el orden de las tablas? (5)

Creo que se puede pensar en esto como un problema de precedencia del operador.

Cuando escribes esto:

FROM groups grp, insrel archiverel LEFT OUTER JOIN ownrel ownrel ON grp.number = ownrel.dnumber LEFT OUTER JOIN tags tags ON tags.number = ownrel.snumber

Creo que es interpretado por el analizador de esta manera:

FROM groups grp, ( ( insrel archiverel LEFT OUTER JOIN ownrel ownrel ON grp.number = ownrel.dnumber ) LEFT OUTER JOIN tags tags ON tags.number = ownrel.snumber )

Si es así, entonces en la unión más interna, "grp" está desatado.

Cuando invierte las líneas con "grupos" y "insrel", la unión más interna se aplica a "grupos" y "ownrel", por lo que funciona.

Probablemente esto funcionaría también:

FROM groups grp JOIN insrel archiverel ON archiverel.dnumber = grp.number LEFT OUTER JOIN ownrel ownrel ON grp.number = ownrel.dnumber LEFT OUTER JOIN tags tags ON tags.number = ownrel.snumber WHERE archiverel.snumber = 11128188

¿Por qué es importante el orden de las tablas cuando se combina una unión externa e interna? lo siguiente falla con postgres:

SELECT grp.number AS number, tags.value AS tag FROM groups grp, insrel archiverel LEFT OUTER JOIN ownrel ownrel ON grp.number = ownrel.dnumber LEFT OUTER JOIN tags tags ON tags.number = ownrel.snumber WHERE archiverel.snumber = 11128188 AND archiverel.dnumber = grp.number

con resultado:

ERROR: invalid reference to FROM-clause entry for table "grp" LINE 5: LEFT OUTER JOIN ownrel ownrel ON grp.number = ownrel.d... ^ HINT: There is an entry for table "grp", but it cannot be referenced from this part of the query.

cuando los grupos se invierten en FROM, todo funciona:

SELECT grp.number AS number, tags.value AS tag FROM insrel archiverel, groups grp LEFT OUTER JOIN ownrel ownrel ON grp.number = ownrel.dnumber LEFT OUTER JOIN tags tags ON tags.number = ownrel.snumber WHERE archiverel.snumber = 11128188 AND archiverel.dnumber = grp.number


No sé qué está causando ese comportamiento, si es un error o diseño, pero debería funcionar bien si te quedas con una forma de unión o la otra.

SELECT grp.number AS number, tags.value AS tag FROM groups grp JOIN insrel archiverel ON archiverel.dnumber = grp.number LEFT OUTER JOIN ownrel ownrel ON grp.number = ownrel.dnumber LEFT OUTER JOIN tags tags ON tags.number = ownrel.snumber WHERE archiverel.snumber = 11128188

Me interesaría saber más si el comportamiento es por diseño.


Para una unión interna, el orden de las tablas no es importante.

Para una unión externa, lo es. Se incluirán todas las filas de la tabla en el lado especificado (es una combinación IZQUIERDA o DERECHA), mientras que solo las filas que coincidan con los criterios de unión se incluirán en la tabla del otro lado.

Debido a que OUTER JOINS mantiene todas las filas desde un lado, se dice que (en general) aumentan los conjuntos de resultados. INNER JOINS solo mantiene las filas de ambos lados si coinciden, por lo que se dice (en general) para reducir los conjuntos de resultados. Por lo tanto, normalmente desea hacer sus UNIONES INTERNAS antes de las UNIONES EXTERNAS (cuando sea posible).

En tu caso, es casi seguro un resultado de la malvada sintaxis A, B.


Porque en la primera grp no es parte de la unión a la que pertenece la cláusula ON.


No creo que nadie haya aclarado esto o lo haya explicado muy bien. Está combinando combinaciones de ''estilo antiguo'' (theta) y ''nuevo estilo'' (ANSI), que sospecho fuertemente que se están agrupando de formas que no espera. Míralo de esta manera:

SELECT * FROM a, b JOIN c ON a.x = c.x

es como decir

SELECT * FROM a, (b JOIN c on a.x = c.x)

donde lo corcheado representa un grupo de tablas fusionadas en una tabla virtual, para unirlas con una combinación theta contra ''a''. Obviamente, la tabla ''a'' no puede ser parte de la unión ya que solo se unirá a ella más tarde. Invétalo, y lo estás haciendo

SELECT * FROM b, (a JOIN c on a.x = c.x)

que es perfectamente comprensible y muy bueno. No estoy seguro de por qué no estás usando la sintaxis de unión ANSI para todo, parece un poco raro (¡y cruel para la persona que tiene que mantenerlo!)