Union de deux tables avec un nombre de colonnes différent

106

J'ai deux tableaux (tableau A et tableau B).

Ceux-ci ont un nombre différent de colonnes - Disons que le tableau A a plus de colonnes.

Comment puis-je unir ces deux tables et obtenir null pour les colonnes que la table B n'a pas?

Jack Kada
la source

Réponses:

215

Ajoutez des colonnes supplémentaires comme nulles pour la table ayant moins de colonnes comme

Select Col1, Col2, Col3, Col4, Col5 from Table1
Union
Select Col1, Col2, Col3, Null as Col4, Null as Col5 from Table2
Kangkan
la source
6
Existe-t-il un moyen de remplir une valeur par défaut pour la colonne Null?
Hans
3
@Hans: Vous pouvez faire quelque chose comme isnull (ColumnName, 0) comme ColumnName ou isnull (ColumnName, '-') comme ColumnName ou quelque chose de similaire.
Kangkan
3
J'ai réalisé que cette solution fonctionne également sans avoir à lister toutes les colonnes. Donc, au lieu de Select Col1, Col2, Col3, Null as Col4, Null as Col5 from Table2, on peut aussi faire Select *, Null as Col4, Null as Col5 from Table2,.
Pratik Patel
Pour la valeur nulle, ce hack a fonctionné pour moi: 'SomeString' comme DummyColumn. Fondamentalement, vous remplacez simplement NULL par une valeur. Cela fonctionnait également lorsqu'il était utilisé avec groupby.
Saurabh Jain le
8

Je suis venu ici et j'ai suivi la réponse ci-dessus. Mais la non-concordance dans l'ordre du type de données a provoqué une erreur. La description ci-dessous d'une autre réponse vous sera utile.

Les résultats ci-dessus sont-ils identiques à la séquence des colonnes de votre tableau? car oracle est strict dans l'ordre des colonnes. cet exemple ci-dessous produit une erreur:

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'expression doit avoir le même type de données que l'expression correspondante

Comme vous le voyez, la cause première de l'erreur réside dans l'ordre des colonnes incompatible qui est impliqué par l'utilisation de * comme spécificateur de liste de colonnes. Ce type d'erreurs peut être facilement évité en entrant explicitement la liste des colonnes:

sélectionnez col_a, col_b, col_c de test1_1790 union tous sélectionnez col_a, col_b, col_c de test2_1790; Un scénario plus fréquent pour cette erreur est lorsque vous échangez (ou déplacez) par inadvertance deux colonnes ou plus dans la liste SELECT:

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

OU si ce qui précède ne résout pas votre problème, que diriez-vous de créer un ALIAS dans les colonnes comme ceci: (la requête n'est pas la même que la vôtre mais le point ici est de savoir comment ajouter un alias dans la colonne.)

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
la source
J'ai dû utiliser la même chose, mais j'ai ajouté a.col_name et b.col_name pour les colonnes non nulles. Pour les colonnes nulles, j'ai dû utiliser: NULL AS col_name1, NULL AS col_name2, etc
Scott R
1
note SELECT * UNION peut être enchaîné plusieurs fois; note WHERE les filtres peuvent être utilisés dans chaque clause SELECT
mirekphd
1

Normalement, vous devez avoir le même nombre de colonnes lorsque vous utilisez des opérateurs basés sur des ensembles afin que la réponse de Kangkan soit correcte.

SAS SQL a un opérateur spécifique pour gérer ce scénario:

SAS (R) 9.3 Guide de l'utilisateur de la procédure SQL

Mot-clé CORRESPONDANT (CORR)

Le mot clé CORRESPONDING est utilisé uniquement lorsqu'un opérateur set est spécifié. CORR oblige PROC SQL à faire correspondre les colonnes des expressions de table par nom et non par position ordinale. Les colonnes qui ne correspondent pas par nom sont exclues de la table de résultats, à l'exception de l'opérateur OUTER UNION.

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

Pour:

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

OUTER UNION CORR

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

<=>

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

U-SQL prend en charge un concept similaire:

UNION EXTÉRIEURE PAR NOM ON (*)

EXTÉRIEUR

nécessite la clause BY NAME et la liste ON. Contrairement aux autres expressions d'ensemble, le schéma de sortie de OUTER UNION inclut à la fois les colonnes correspondantes et les colonnes non correspondantes des deux côtés. Cela crée une situation où chaque ligne provenant de l'un des côtés a des "colonnes manquantes" qui ne sont présentes que de l'autre côté. Pour ces colonnes, les valeurs par défaut sont fournies pour les "cellules manquantes". Les valeurs par défaut sont nulles pour les types Nullable et la valeur par défaut .Net pour les types non Nullables (par exemple, 0 pour int).

DE NOM

est requis lorsqu'il est utilisé avec OUTER. La clause indique que l'union fait correspondre les valeurs non pas en fonction de la position, mais du nom des colonnes. Si la clause BY NAME n'est pas spécifiée, la mise en correspondance est effectuée en position.

Si la clause ON inclut le symbole «*» (il peut être spécifié comme le dernier ou le seul membre de la liste), alors les correspondances de nom supplémentaires au-delà de celles de la clause ON sont autorisées et les colonnes du résultat incluent toutes les colonnes correspondantes dans le l'ordre dans lequel ils sont présents dans l'argument de gauche.

Et code:

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

ÉDITER:

Le concept d'union externe est pris en charge par KQL :

gentil:

inner - Le résultat a le sous-ensemble de colonnes qui sont communes à toutes les tables d'entrée.

externe - Le résultat contient toutes les colonnes qui apparaissent dans l'une des entrées. Les cellules qui n'ont pas été définies par une ligne d'entrée sont définies sur null.

Exemple:

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;

Production:

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

démo

Lukasz Szozda
la source
Une idée comment y parvenir en SQL?
KetanVaghasiya
@KetanVaghasiya Pour autant que je sache, seuls SAS SQL et U-SQL prennent en charge ce concept.
Lukasz Szozda
-1

si seulement 1 ligne, vous pouvez utiliser join

Select t1.Col1, t1.Col2, t1.Col3, t2.Col4, t2.Col5 from Table1 t1 join Table2 t2;
Sai Sai
la source
Une union de deux tables à 1 ligne (deux relations multisets chacune avec un tuple) aurait deux lignes (tuples) dans la relation résultante. En algèbre relationnelle (ce que SQL n'est pas), le résultat de l'union pourrait être une ligne, mais seulement si les deux relations d'entrée contenaient un tuple identique, par exemple. auto-union d'une relation à un tuple.
Robert Monfera