Vereinigen von zwei Tabellen mit unterschiedlicher Anzahl von Spalten

106

Ich habe zwei Tabellen (Tabelle A und Tabelle B).

Diese haben eine unterschiedliche Anzahl von Spalten - Angenommen, Tabelle A enthält mehr Spalten.

Wie kann ich diese beiden Tabellen vereinen und null für die Spalten erhalten, die Tabelle B nicht hat?

Jack Kada
quelle

Antworten:

215

Fügen Sie zusätzliche Spalten als Null für die Tabelle mit weniger Spalten hinzu

Select Col1, Col2, Col3, Col4, Col5 from Table1
Union
Select Col1, Col2, Col3, Null as Col4, Null as Col5 from Table2
Kangkan
quelle
6
Gibt es eine Möglichkeit, einen Standardwert für die Nullspalte einzugeben?
Hans
3
@Hans: Sie können so etwas wie isnull (ColumnName, 0) als ColumnName oder isnull (ColumnName, '-') als ColumnName oder ähnliches ausführen.
Kangkan
3
Mir wurde klar, dass diese Lösung auch funktioniert, ohne alle Spalten auflisten zu müssen. Also statt Select Col1, Col2, Col3, Null as Col4, Null as Col5 from Table2kann man auch , Select *, Null as Col4, Null as Col5 from Table2.
Pratik Patel
Für den Nullwert funktionierte dieser Hack für mich: 'SomeString' als DummyColumn. Grundsätzlich ersetzen Sie einfach NULL durch einen Wert. Dies funktionierte auch bei Verwendung mit groupby.
Saurabh Jain
8

Ich kam hierher und folgte der obigen Antwort. Eine Nichtübereinstimmung in der Reihenfolge des Datentyps verursachte jedoch einen Fehler. Die folgende Beschreibung aus einer anderen Antwort wird nützlich sein.

Entsprechen die obigen Ergebnisse der Spaltenfolge in Ihrer Tabelle? weil Orakel in Spaltenreihenfolgen streng ist. Dieses Beispiel unten erzeugt einen Fehler:

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: Ausdruck muss denselben Datentyp wie der entsprechende Ausdruck haben

Wie Sie sehen, liegt die Hauptursache des Fehlers in der nicht übereinstimmenden Spaltenreihenfolge, die durch die Verwendung von * als Spaltenlistenspezifizierer impliziert wird. Diese Art von Fehlern kann leicht vermieden werden, indem die Spaltenliste explizit eingegeben wird:

wähle col_a, col_b, col_c aus test1_1790 union alle wähle col_a, col_b, col_c aus test2_1790; Ein häufigeres Szenario für diesen Fehler ist, wenn Sie versehentlich zwei oder mehr Spalten in der SELECT-Liste vertauschen (oder verschieben):

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

ODER wenn das oben genannte Problem nicht gelöst werden kann, können Sie einen ALIAS in den folgenden Spalten erstellen : (Die Abfrage ist nicht mit Ihrer identisch, aber hier geht es darum, wie Sie einen Alias ​​in die Spalte einfügen .)

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
quelle
Ich musste dasselbe verwenden, aber ich habe a.col_name und b.col_name für Nicht-Null-Spalten hinzugefügt. Für Nullspalten musste ich verwenden: NULL AS col_name1, NULL AS col_name2 usw.
Scott R
1
note SELECT * UNION kann mehrfach verkettet werden. note WHERE-Filter können in jeder SELECT-Klausel verwendet werden
mirekphd
1

Normalerweise müssen Sie die gleiche Anzahl von Spalten haben, wenn Sie satzbasierte Operatoren verwenden, damit Kangkans Antwort korrekt ist.

SAS SQL verfügt über einen bestimmten Operator für dieses Szenario:

SAS (R) 9.3 SQL-Prozedur Benutzerhandbuch

Schlüsselwort CORRESPONDING (CORR)

Das Schlüsselwort CORRESPONDING wird nur verwendet, wenn ein Set-Operator angegeben ist. CORR bewirkt, dass PROC SQL den Spalten in Tabellenausdrücken nach Namen und nicht nach Ordnungsposition entspricht. Spalten, die nicht nach Namen übereinstimmen, werden mit Ausnahme des Operators OUTER UNION aus der Ergebnistabelle ausgeschlossen.

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

Zum:

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

OUTER UNION CORR

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

<=>

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

U-SQL unterstützt ein ähnliches Konzept:

AUSSENUNION NAMEN EIN (*)

ÄUSSERE

erfordert die BY NAME-Klausel und die ON-Liste. Im Gegensatz zu den anderen Mengenausdrücken enthält das Ausgabeschema der OUTER UNION sowohl die übereinstimmenden Spalten als auch die nicht übereinstimmenden Spalten von beiden Seiten. Dies schafft eine Situation, in der jede Zeile, die von einer der Seiten kommt, "fehlende Spalten" hat, die nur auf der anderen Seite vorhanden sind. Für solche Spalten werden Standardwerte für die "fehlenden Zellen" angegeben. Die Standardwerte sind null für nullbare Typen und der .Net-Standardwert für nicht nullbare Typen (z. B. 0 für int).

NAMENTLICH

wird bei Verwendung mit OUTER benötigt. Die Klausel gibt an, dass die Union Werte nicht basierend auf der Position, sondern nach dem Namen der Spalten abgleichen. Wenn die BY NAME-Klausel nicht angegeben ist, erfolgt der Abgleich positionell.

Wenn die ON-Klausel das Symbol "*" enthält (es kann als letztes oder einziges Mitglied der Liste angegeben werden), sind zusätzliche Namensübereinstimmungen zulässig, die über die in der ON-Klausel angegebenen hinausgehen, und die Spalten des Ergebnisses enthalten alle übereinstimmenden Spalten in der Reihenfolge sind sie im linken Argument vorhanden.

Und Code:

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

BEARBEITEN:

Das Konzept der äußeren Vereinigung wird von KQL unterstützt :

nett:

inner - Das Ergebnis enthält die Teilmenge der Spalten, die allen Eingabetabellen gemeinsam sind.

Outer - Das Ergebnis enthält alle Spalten, die in einer der Eingaben vorkommen. Zellen, die nicht durch eine Eingabezeile definiert wurden, werden auf null gesetzt.

Beispiel:

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;

Ausgabe:

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

Demo

Lukasz Szozda
quelle
Irgendeine Idee, wie man dies in SQL erreicht?
KetanVaghasiya
@ KetanVaghasiya Soweit ich weiß, unterstützen nur SAS SQL und U-SQL dieses Konzept.
Lukasz Szozda
-1

Wenn nur 1 Zeile, können Sie join verwenden

Select t1.Col1, t1.Col2, t1.Col3, t2.Col4, t2.Col5 from Table1 t1 join Table2 t2;
Sai Sai
quelle
Eine Vereinigung von zwei 1-Zeilen-Tabellen (zwei Multiset-Beziehungen mit jeweils einem Tupel) hätte zwei Zeilen (Tupel) in der resultierenden Beziehung. In relationalen Algebra (die SQL nicht) die Vereinigung Ergebnis könnte eine Zeile, werden allerdings nur , wenn die beiden Eingangs Beziehungen eine identische Tupel enthalten, z. B. Selbstvereinigung einer Ein-Tupel-Beziehung.
Robert Monfera