在SQL中从一行中选择多行

时间:2011-02-13 08:35:55

标签: c# sql sql-server tsql

我从多个表中获得以下输出

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  

现在我想将这些值插入另一个表中,单个命令的insert查询如下:

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

为此,我需要做一个选择,以便它给我

id,b,c
id,b,e etc

我也不介意摆脱b,因为可以使用c#query选择它。

如何在sql中使用单个查询来实现相同的功能。请再次注意,它不是一个表,它是来自不同表的输出

我的查询应该如下所示:从上面我需要做一些像

这样的事情
select b.a, b.c
union all
select b.d,b.e from  (select a,c,d,e from <set of join>)  b

但不幸的是,这不起作用

4 个答案:

答案 0 :(得分:2)

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

您的示例有几个名为'b'的列,不允许使用...

答案 1 :(得分:2)

此处,#tmporigin是指您在问题中生成数据的原始查询。只需用子查询替换表名。

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

<小时/>

下面的原始答案,使用CTE和union,都要求CTE评估3次

  

我从多个表中获得以下输出

因此,将该查询设置为公用表表达式

;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

注意 - 与流行的看法相反,您的CTE在方便地编写一次时,在上述查询中运行三次,每次联合所有部分都会运行一次。

请注意,如果您实际上将3列命名为“b”(字面意思),则无法确定在您尝试引用结果的任何内容中引用的b - 实际上SQL Server不允许您在CTE或子查询中使用查询。

以下示例显示了如何执行上述操作,以及(如果您显示执行计划)显示CTE运行3次! (--- BELOW HERE--- ABOVE HERE之间的行是模拟问题中产生输出的original query

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

在进行union all选择之前,最好将数据存储到临时表中。

答案 2 :(得分:0)

而不是像你所知的那样无效

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

你可以这样做。联盟重复分选

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

或者这个。反复使用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

或者使用临时表变量。

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

此代码未经过测试,因此可能存在任何数量的拼写错误。

答案 3 :(得分:0)

我不确定我是否理解你的问题,但我已经使用过这样的东西一段时间了:

假设我们有一张桌子

ID Val1 Val2
1 A B
2 C D

获得像

这样的结果

ID Val
1 A
1 B
2 C
2 D

您可以使用查询:

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

将简单地将表与包含两个值的子查询连接起来,并创建一个笛卡尔积。实际上,所有行都将加倍(或乘以子查询将具有的值)。您可以根据您需要的行数来改变值的数量。根据i的值,Val将是原始表中的Val1或Val2。如果您将看到执行计划,则会出现一个警告:连接没有连接谓词(因为i = i),但是没关系 - 我们想要它。 这使得查询有点大(在文本方面),因为所有情况都是,但如果格式正确则很容易阅读。我需要它用于愚蠢的表,如“BigID,smallID1,smallID2 ... smallID11”,它分布在许多列,我不知道为什么。 希望能帮助到你。 哦,我使用10000个数字的静态表,所以我只使用

join tab10k on i<=10

10x行。 我为愚蠢的格式道歉,我是新来的。