Uniendo dos tablas con diferente número de columnas

Resuelto Jack Kada asked hace 14 años • 5 respuestas

Tengo dos tablas (Tabla A y Tabla B).

Estos tienen un número diferente de columnas: digamos que la tabla A tiene más columnas.

¿Cómo puedo unir estas dos tablas y obtener valores nulos para las columnas que la Tabla B no tiene?

Jack Kada avatar Feb 22 '10 16:02 Jack Kada
Aceptado

Agregue columnas adicionales como nulas para la tabla que tiene menos columnas como

Select Col1, Col2, Col3, Col4, Col5 from Table1
Union
Select Col1, Col2, Col3, Null as Col4, Null as Col5 from Table2
Kangkan avatar Feb 22 '2010 09:02 Kangkan

Vine aquí y seguí la respuesta anterior. Pero la falta de coincidencia en el orden del tipo de datos provocó un error. La siguiente descripción de otra respuesta será útil.

¿Los resultados anteriores son los mismos que la secuencia de columnas de su tabla? porque Oracle es estricto en el orden de las columnas. este ejemplo a continuación produce un error:

create table test1_1790 (
col_a varchar2(30),
col_b number,
col_c date);

create table test2_1790 (
col_a varchar2(30),
col_c date,
col_b number);

select * from test1_1790
union all
select * from test2_1790;

ORA-01790: la expresión debe tener el mismo tipo de datos que la expresión correspondiente

Como puede ver, la causa principal del error está en el orden de las columnas que no coincide, lo que implica el uso de * como especificador de lista de columnas. Este tipo de errores se pueden evitar fácilmente ingresando explícitamente la lista de columnas:

seleccione col_a, col_b, col_c de test1_1790 unión todos seleccione col_a, col_b, col_c de test2_1790; Un escenario más frecuente para este error es cuando sin darse cuenta intercambia (o desplaza) dos o más columnas en la lista SELECT:

select col_a, col_b, col_c from test1_1790
union all
select col_a, col_c, col_b from test2_1790;

O si lo anterior no resuelve su problema, ¿qué tal si crea un ALIAS en las columnas como esta? (La consulta no es la misma que la suya, pero el punto aquí es cómo agregar un alias en la columna).

SELECT id_table_a, 
       desc_table_a, 
       table_b.id_user as iUserID, 
       table_c.field as iField
UNION
SELECT id_table_a, 
       desc_table_a, 
       table_c.id_user as iUserID, 
       table_c.field as iField
Anand Varkey Philips avatar Nov 23 '2016 09:11 Anand Varkey Philips

Normalmente, necesita tener la misma cantidad de columnas cuando usa operadores basados ​​en conjuntos para que la respuesta de Kangkan sea correcta.

SAS SQL tiene un operador específico para manejar ese escenario:

Guía del usuario del procedimiento SQL SAS(R) 9.3

Palabra clave CORRESPONDIENTE (CORR)

La palabra clave CORRESPONDING se utiliza sólo cuando se especifica un operador de conjunto. CORR hace que PROC SQL coincida con las columnas de las expresiones de la tabla por nombre y no por posición ordinal. Las columnas que no coinciden por nombre se excluyen de la tabla de resultados, excepto el operador OUTER UNION.

SELECT * FROM tabA
OUTER UNION CORR
SELECT * FROM tabB;

Para:

+---+---+
| a | b |
+---+---+
| 1 | X |
| 2 | Y |
+---+---+

OUTER UNION CORR

+---+---+
| b | d |
+---+---+
| U | 1 |
+---+---+

<=>

+----+----+---+
| a  | b  | d |
+----+----+---+
|  1 | X  |   |
|  2 | Y  |   |
|    | U  | 1 |
+----+----+---+

U-SQL admite un concepto similar:

UNIÓN EXTERIOR POR NOMBRE EN (*)

EXTERIOR

requiere la cláusula BY NAME y la lista ON. A diferencia de otras expresiones de conjunto, el esquema de salida de OUTER UNION incluye tanto las columnas coincidentes como las columnas no coincidentes de ambos lados. Esto crea una situación en la que a cada fila que viene de uno de los lados le faltan "columnas" que están presentes sólo en el otro lado. Para dichas columnas, se proporcionan valores predeterminados para las "celdas que faltan". Los valores predeterminados son nulos para los tipos que aceptan valores NULL y el valor predeterminado de .Net para los tipos que no admiten NULL (por ejemplo, 0 para int).

POR NOMBRE

es necesario cuando se utiliza con OUTER. La cláusula indica que la unión hace coincidir valores no según la posición sino por el nombre de las columnas. Si no se especifica la cláusula BY NAME, la coincidencia se realiza posicionalmente.

Si la cláusula ON incluye el símbolo “*” (puede especificarse como el último o el único miembro de la lista), entonces se permiten coincidencias de nombres adicionales además de las de la cláusula ON, y las columnas del resultado incluirán todas las columnas coincidentes en la orden en que están presentes en el argumento de la izquierda.

Y código:

@result =    
    SELECT * FROM @left
    OUTER UNION BY NAME ON (*) 
    SELECT * FROM @right;

EDITAR:

El concepto de unión externa está respaldado por KQL :

amable:

interno: el resultado tiene el subconjunto de columnas que son comunes a todas las tablas de entrada.

exterior: el resultado tiene todas las columnas que aparecen en cualquiera de las entradas. Las celdas que no fueron definidas por una fila de entrada se establecen en nulo.

Ejemplo:

let t1 = datatable(col1:long, col2:string)  
[1, "a",  
2, "b",
3, "c"];
let t2 = datatable(col3:long)
[1,3];
t1 | union kind=outer t2;

Producción:

+------+------+------+
| col1 | col2 | col3 |
+------+------+------+
|    1 | a    |      |
|    2 | b    |      |
|    3 | c    |      |
|      |      |    1 |
|      |      |    3 |
+------+------+------+

DuckDB - UNIÓN (TODOS) POR NOMBRE

La cláusula UNION (ALL) BY NAME se puede utilizar para combinar filas de diferentes tablas por nombre, en lugar de por posición. UNION BY NAME no requiere que ambas consultas tengan el mismo número de columnas. Cualquier columna que solo se encuentre en una de las consultas se completa con valores NULL para la otra consulta.

SELECT * FROM capitals UNION BY NAME SELECT * FROM weather;


┌───────────┬─────────┬─────────┬────────────┐
│   city    │ country │ degrees │    date    │
│  varcharvarchar │  int32  │    date    │
├───────────┼─────────┼─────────┼────────────┤
│ Amsterdam │ NULL102022-10-14 │
│ Seattle   │ NULL82022-10-12 │
│ Amsterdam │ NL      │    NULLNULL       │
│ Berlin    │ Germany │    NULLNULL       │
└───────────┴─────────┴─────────┴────────────┘
Lukasz Szozda avatar Sep 26 '2018 18:09 Lukasz Szozda

En PostgreSQL existe la opción de un archivo NATURAL FULL JOIN. Tu puedes hacer:

SELECT *
FROM
    (SELECT *, 't1' AS source FROM t1) AS t1
NATURAL FULL JOIN
    (SELECT *, 't2' AS source FROM t2) AS t2
;

Como lo mencionó @ lukasz-szozda en un comentario a la pregunta del OP, refiriéndose a esta respuesta .

andschar avatar Aug 04 '2023 09:08 andschar