开发者

Selecting multiple row from one row in SQL

I have the following output with me from multiple 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  

Now I want to insert these values into another table and the insert query for a single command is as follows:

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

For that I need to do a select such that it gives me

id,b,c
id,b,e etc

I dont mind getting rid of b too as it can be selected using c# query.

How can I achieve the same using a single query 开发者_如何学编程in sql. Again please note its not a table its an output from different tables

My query should look as follows: from the above I need to do something like

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

But unfortunately that does not work


INSERT resulttable
SELECT id, b, c
FROM original
UNION
SELECT id, b, e
FROM original

Your example has several columns named 'b' which isn't allowed...


Here, #tmporigin refers to your original query that produces the data in the question. Just replace the table name with a subquery.

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


The original answer below, using CTE and union all requiring CTE evaluation 3 times

I have the following output with me from multiple tables

So set that query up as a Common Table Expression

;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 - Contrary to popular belief, your CTE while conveniently written once, is run thrice in the above query, once for each of the union all parts.

NOTE ALSO that if you actually name 3 columns "b" (literally), there is no way to identify which b you are referring to in anything that tries to reference the results - in fact SQL Server will not let you use the query in a CTE or subquery.

The following example shows how to perform the above, as well as (if you show the execution plan) revealing that the CTE is run 3 times! (the lines between --- BELOW HERE and --- ABOVE HERE is a mock of the original query that produces the output in the 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

You would be better off storing the data into a temp table before doing the union all select.


Instead of this which does not work as you know

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

You can do this. Union with repeated sub-select

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

Or this. Repeated use of 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

Or use a temporary table variable.

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

This code is not tested so there might be any number of typos in there.


I'm not sure if I understood Your problem correctly, but i have been using something like this for some time:

let's say we have a table

ID Val1 Val2
1 A B
2 C D

to obtain a reslut like

ID Val
1 A
1 B
2 C
2 D

You can use a query :

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

which will simply join the table with a subquery containing two values and create a cartesian product. In effect, all rows will be doubled (or multiplied by how many values the subquery will have). You can vary the number of values depending on how many varsions of row You'll need. Depending on the value of i, Val will be Val1 or Val2 from original table. If you'll see the execution plan, there will be a warning that the join has no join predicates (because of i=i), but it is ok - we want it. This makes queries a bit large (in terms of text) because of all the case when, but are quite easy to read if formatted right. I needed it for stupid tables like "BigID, smallID1, smallID2...smallID11" that was spread across many columns I don't know why. Hope it helps. Oh, I use a static table with 10000 numbers, so i just use

join tab10k on i<=10

for 10x row. I apologize for stupid formatting, I'm new here.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜