3 votes

Sélectionner plusieurs lignes à partir d'une seule ligne en SQL

J'ai les résultats suivants provenant de plusieurs tables

id    b   c   b     e    b     g  
abc  2   123  3   321   7   876  
abd  2   456  3   452   7   234  
abe  2   0    3   123   7   121  
abf  2   NULL 3   535   7   1212  

Je veux maintenant insérer ces valeurs dans une autre table et la requête d'insertion pour une commande unique est la suivante :

insert into resulttable values (id,b,c), (id,b,e) etc.

Pour cela, je dois faire une sélection qui me donne

id,b,c
id,b,e etc

Je ne vois pas d'inconvénient à ce que l'on se débarrasse aussi de b car il peut être sélectionné à l'aide d'une requête c#.

Comment puis-je réaliser la même chose en utilisant une seule requête en SQL. Encore une fois, veuillez noter qu'il ne s'agit pas d'une table mais d'une sortie de différentes tables.

Ma requête devrait ressembler à ce qui suit : à partir de ce qui précède, je dois faire quelque chose comme

select b.a, b.c
union all
select b.d,b.e from  (select a,c,d,e from <set of join>)  b

Malheureusement, cela ne fonctionne pas

2voto

Jason Goemaat Points 7211
INSERT resulttable
SELECT id, b, c
FROM original
UNION
SELECT id, b, e
FROM original

Votre exemple comporte plusieurs colonnes nommées "b", ce qui n'est pas autorisé...

2voto

RichardTheKiwi Points 58121

Ici, #tmporigin fait référence à votre requête originale qui produit les données de la question. Il suffit de remplacer le nom de la table par une sous-requête.

insert into resulttable
select
 o.id,
 case a.n when 1 then b1 when 2 then b2 else b3 end,
 case a.n when 1 then c when 2 then e else g end
from #tmporigin o
cross join (select 1n union all select 2 union all select 3) a

La réponse originale ci-dessous, qui utilise la CTE et l'union, nécessite une évaluation de la CTE à trois reprises.

J'ai les résultats suivants provenant de plusieurs tables

Configurez donc cette requête en tant qu'expression de table commune.

;WITH CTE AS (
   -- the query that produces that output
)
select id,b1,c from CTE
union all
select id,b2,e from CTE
union all
select id,b3,g from CTE

NOTE - Contrairement à la croyance populaire, votre CTE, bien qu'écrit une seule fois, est exécuté. trois fois dans la requête ci-dessus, une fois pour chacune des parties de l'union.

NOTE AUSSI que si l'on nomme 3 colonnes "b" (littéralement), il n'y a aucun moyen d'identifier laquelle est "b". b En fait, SQL Server ne vous permettra pas d'utiliser la requête dans un CTE ou une sous-requête.

L'exemple suivant montre comment effectuer ce qui précède et révèle (si vous montrez le plan d'exécution) que l'ETC est exécuté trois fois ! (les lignes entre --- BELOW HERE et --- ABOVE HERE est un simulacre de la original query qui produit le résultat indiqué dans la question.

if object_id('tempdb..#eav') is not null drop table #eav
;
create table #eav (id char(3), b int, v int)
insert #eav select 'abc', 2, 123
insert #eav select 'abc', 3, 321
insert #eav select 'abc', 7, 876
insert #eav select 'abd', 2, 456
insert #eav select 'abd', 3, 452
insert #eav select 'abd', 7, 234
insert #eav select 'abe', 2, 0
insert #eav select 'abe', 3, 123
insert #eav select 'abe', 7, 121
insert #eav select 'abf', 3, 535
insert #eav select 'abf', 7, 1212

;with cte as (
---- BELOW HERE
    select id.id, b1, b1.v c, b2, b2.v e, b3, b3.v g
    from
    (select distinct id, 2 as b1, 3 as b2, 7 as b3 from #eav) id
    left join #eav b1 on b1.b=id.b1 and b1.id=id.id
    left join #eav b2 on b2.b=id.b2 and b2.id=id.id
    left join #eav b3 on b3.b=id.b3 and b3.id=id.id
---- ABOVE HERE
)
select b1, c from cte
union all
select b2, e from cte
union all
select b3, g from cte
order by b1

Il est préférable de stocker les données dans une table temporaire avant de procéder à l'opération union all sélectionner.

0voto

Mikael Eriksson Points 77190

Au lieu de cela, qui ne fonctionne pas comme vous le savez

select b.a, b.c
union all
select b.d,b.e from  (select a,c,d,e from <set of join>)  b

Vous pouvez le faire. Union avec sous-sélection répétée

select b.a, b.c from (select a,c,d,e from <set of join>)  b
union all
select b.d, b.e from (select a,c,d,e from <set of join>)  b

Ou encore ceci. Utilisation répétée de cte.

with cte as
(select a,c,d,e from <set of join>)
select b.a, b.c from cte b
union all
select b.d, b.e from cte b

Ou utilisez une variable de table temporaire.

declare @T table (a int, c int, d int, e int)
insert into @T values
select a,c,d,e from <set of join>

select b.a, b.c from @T  b
union all
select b.d, b.e from @T  b

Ce code n'a pas été testé, il peut donc contenir un certain nombre de fautes de frappe.

0voto

Alan here Points 1

Je ne suis pas sûr d'avoir bien compris votre problème, mais j'utilise quelque chose de ce genre depuis un certain temps :

Disons que nous avons un tableau

ID Val1 Val2 1 A B 2 C D

d'obtenir une femme comme

ID Val 1 A 1 B 2 C 2 D

Vous pouvez utiliser une requête :

select ID, case when i=1 then Val1 when i=2 then Val2 end as Val
from table
left join ( select 1 as i union all select 2 as i ) table_i on i=i

qui joindra simplement la table avec une sous-requête contenant deux valeurs et créera un produit cartésien. En fait, toutes les lignes seront doublées (ou multipliées par le nombre de valeurs de la sous-requête). Vous pouvez varier le nombre de valeurs en fonction du nombre de versions de ligne dont vous aurez besoin. En fonction de la valeur de i, Val sera Val1 ou Val2 de la table d'origine. Si vous voyez le plan d'exécution, il y aura un avertissement que la jointure n'a pas de prédicats de jointure (à cause de i=i), mais ce n'est pas grave - c'est ce que nous voulons. Cela rend les requêtes un peu volumineuses (en termes de texte) à cause de la casse, mais elles sont assez faciles à lire si elles sont formatées correctement. J'en ai eu besoin pour des tables stupides comme "BigID, smallID1, smallID2...smallID11" qui étaient réparties sur de nombreuses colonnes, je ne sais pas pourquoi. J'espère que cela vous aidera. Oh, j'utilise une table statique avec 10000 nombres, donc j'utilise juste

join tab10k on i<=10

pour une rangée de 10x. Je m'excuse pour le formatage stupide, je suis nouveau ici.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X