Unione di due tabelle con diverso numero di colonne


106

Ho due tavoli (Tabella A e Tabella B).

Questi hanno un numero diverso di colonne: supponiamo che la tabella A abbia più colonne.

Come posso unire queste due tabelle e ottenere null per le colonne che la tabella B non ha?

Risposte:


215

Aggiungi colonne extra come null per la tabella con meno colonne come

Select Col1, Col2, Col3, Col4, Col5 from Table1
Union
Select Col1, Col2, Col3, Null as Col4, Null as Col5 from Table2

6
C'è un modo per inserire un valore predefinito per la colonna Null?
Hans

3
@ Hans: Puoi fare qualcosa come isnull (ColumnName, 0) come ColumnName o isnull (ColumnName, '-') come ColumnName o qualcosa di simile.
Kangkan

3
Mi sono reso conto che questa soluzione funziona anche senza dover elencare tutte le colonne. Quindi invece di Select Col1, Col2, Col3, Null as Col4, Null as Col5 from Table2, si può anche fare Select *, Null as Col4, Null as Col5 from Table2,.
Pratik Patel

Per il valore null, questo hack ha funzionato per me: 'SomeString' come DummyColumn. Fondamentalmente, sostituisci semplicemente NULL con un valore. Funzionava anche se usato con groupby.
Saurabh Jain

8

Sono venuto qui e ho seguito la risposta sopra. Ma la mancata corrispondenza nell'ordine del tipo di dati ha causato un errore. La descrizione di seguito da un'altra risposta tornerà utile.

I risultati sopra sono gli stessi della sequenza di colonne nella tua tabella? perché Oracle è rigoroso negli ordini di colonna. questo esempio seguente produce un errore:

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: l'espressione deve avere lo stesso tipo di dati dell'espressione corrispondente

Come puoi vedere, la causa principale dell'errore è nell'ordinamento delle colonne non corrispondente che è implicito nell'uso di * come specificatore dell'elenco di colonne. Questo tipo di errore può essere facilmente evitato inserendo esplicitamente l'elenco delle colonne:

seleziona col_a, col_b, col_c da test1_1790 union all seleziona col_a, col_b, col_c da test2_1790; Uno scenario più frequente per questo errore è quando si scambiano (o si sposta) inavvertitamente due o più colonne nell'elenco SELEZIONA:

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

O se quanto sopra non risolve il tuo problema, che ne dici di creare un ALIAS nelle colonne in questo modo: (la query non è la tua ma il punto qui è come aggiungere alias nella colonna.)

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

Ho dovuto usare la stessa cosa, ma ho aggiunto a.col_name e b.col_name per le colonne non nulle. Per le colonne null, ho dovuto usare: NULL AS col_name1, NULL AS col_name2, ecc.
Scott R

1
nota SELECT * UNION può essere concatenato più volte; nota WHERE i filtri possono essere utilizzati in ogni clausola SELECT
mirekphd

1

Normalmente è necessario avere lo stesso numero di colonne quando si utilizzano operatori basati su set, quindi la risposta di Kangkan è corretta.

SAS SQL ha un operatore specifico per gestire quello scenario:

SAS (R) 9.3 Guida utente procedura SQL

Parola chiave CORRISPONDENTE (CORR)

La parola chiave CORRESPONDING viene utilizzata solo quando viene specificato un operatore di gruppo. CORR fa sì che PROC SQL corrisponda alle colonne nelle espressioni di tabella in base al nome e non in base alla posizione ordinale. Le colonne che non corrispondono in base al nome vengono escluse dalla tabella dei risultati, ad eccezione dell'operatore UNIONE ESTERNA.

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

Per:

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

OUTER UNION CORR

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

<=>

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

U-SQL supporta un concetto simile:

UNIONE ESTERNA PER NOME IL (*)

ESTERNO

richiede la clausola BY NAME e l'elenco ON. A differenza delle altre espressioni di insieme, lo schema di output dell'UNIONE ESTERNA include sia le colonne corrispondenti che le colonne non corrispondenti da entrambi i lati. Questo crea una situazione in cui ogni riga proveniente da uno dei lati ha "colonne mancanti" che sono presenti solo sull'altro lato. Per tali colonne, vengono forniti valori predefiniti per le "celle mancanti". I valori predefiniti sono null per i tipi nullable e il valore predefinito .Net per i tipi non nullable (ad esempio, 0 per int).

PER NOME

è richiesto se utilizzato con OUTER. La clausola indica che l'unione corrisponde a valori non basati sulla posizione ma sul nome delle colonne. Se la clausola BY NAME non è specificata, la corrispondenza viene eseguita in modo posizionale.

Se la clausola ON include il simbolo "*" (può essere specificato come l'ultimo o l'unico membro dell'elenco), sono consentite corrispondenze di nomi extra oltre a quelle nella clausola ON e le colonne del risultato includono tutte le colonne corrispondenti nella nell'ordine in cui sono presenti nell'argomento a sinistra.

E codice:

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

MODIFICARE:

Il concetto di unione esterna è supportato da KQL :

genere:

inner: il risultato ha il sottoinsieme di colonne comuni a tutte le tabelle di input.

esterno: il risultato ha tutte le colonne che si trovano in uno degli input. Le celle che non sono state definite da una riga di input vengono impostate su null.

Esempio:

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;

Produzione:

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

dimostrazione


Qualche idea su come ottenerlo in SQL ??
KetanVaghasiya

@KetanVaghasiya Per quanto ne so, solo SAS SQL e U-SQL supportano questo concetto.
Lukasz Szozda

-1

se solo 1 riga, puoi usare join

Select t1.Col1, t1.Col2, t1.Col3, t2.Col4, t2.Col5 from Table1 t1 join Table2 t2;

Un'unione di due tabelle di 1 riga (due relazioni multiset ciascuna con una tupla) avrebbe due righe (tuple) nella relazione risultante. Nell'algebra relazionale (che SQL non è) il risultato dell'unione potrebbe essere una riga, anche se solo se le due relazioni di input contenevano una tupla identica, ad es. autounione di una relazione a una tupla.
Robert Monfera
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.