繁体   English   中英

单个SQL SELECT从一个表行返回多行

[英]Single SQL SELECT Returning multiple rows from one table row

我们有一个表格,其形式为:

ID,Value1,Value2,Value3
1,2,3,4

我们需要将其转化为。

ID,Name,Value
1,'Value1',2
1,'Value2',3
1,'Value3',4

在一个SELECT语句中是否有一种聪明的方法(即没有UNION)? 列名称Value1,Value2和Value3是固定的且恒定的。

该数据库是oracle 9i。

union一个机会。

select ID, 'Value1' as Name, Value1 as Value from table_name union all
select ID, 'Value2', Value2 as Value from table_name union all
select ID, 'Value3', Value3 as Value from table_name

order by ID, Name

使用union all意味着服务器将不执行distinct (这是隐含在union的操作)。 它不会对数据造成任何影响(因为您的ID应该很不同),但是可能会加快速度。

这适用于Oracle 10g:

select id, 'Value' || n as name,
       case n when 1 then value1 when 2 then value2 when 3 then value3 end as value
from (select rownum n
      from (select 1 from dual connect by level <= 3)) ofs, t

我认为Oracle 9i有递归查询吗? 无论如何,我非常确定它具有CASE支持,因此即使它没有递归查询,也可以执行“(从双联合中选择1,从双联合中选择2,从双联合中选择3,全部从双中选择3)”代替。 对于Oracle,滥用递归查询会更普遍一些。 (不过,使用联合生成行可移植到其他数据库中)

您可以像这样进行操作,但效果并不理想:

SELECT id,'Value 1' AS name,value1 AS value FROM mytable
UNION
SELECT id,'Value 2' AS name,value2 AS value FROM mytable
UNION
SELECT id,'Value 3' AS name,value3 AS value FROM mytable

合并三个选择语句应该可以解决问题:

SELECT ID, 'Value1', Value1 AS Value
FROM TABLE
UNION
SELECT ID, 'Value2', Value2 AS Value
FROM TABLE
UNION
SELECT ID, 'Value3', Value3 AS Value
FROM TABLE

对于Oracle(我在Teradata中运行过),CTE语法可能有所不同,但是我仅使用CTE提供测试数据,即1 2 3和4。可以使用临时表代替。 实际的select语句是普通的香草SQL,它将在任何关系数据库上使用。

如果您使用的是SQL Server 2005+,则可以使用UNPIVOT

CREATE TABLE #tmp ( ID int, Value1 int, Value2 int, Value3 int)

INSERT INTO #tmp (ID, Value1, Value2, Value3) VALUES (1, 2, 3, 4)

SELECT
    *
FROM
    #tmp

SELECT
    *
FROM
    #tmp
UNPIVOT
(
    [Value] FOR [Name] IN (Value1, Value2, Value3)
) uPIVOT

DROP TABLE #tmp

正如其他人所建议的,UNION ALL可能是您在SQL中最好的选择。 您可能还需要考虑根据自己的特定要求在前端进行处理。

尝试这个:

CTE创建具有4个值的临时表。 您可以在任何数据库中按原样运行它。

with TEST_CTE (ID) as

(select * from (select '1' as a) as aa  union all
select * from (select '2' as b) as bb  union all
select * from (select '3' as c) as cc  union all
select * from (select '4' as d) as dd )

select a.ID, 'Value'|| a.ID, b.ID
from TEST_CTE a, TEST_CTE b
where b.ID = (select min(c.ID) from TEST_CTE c where c.ID > a.ID)

这是结果集:

1   Value1  2

2   Value2  3

3   Value3  4

请享用!

一些事后思考。

^^^ CTE语法在Oracle中可能有所不同。 我只能在Teradata中运行它。 您可以将其替换为临时表,也可以修复语法以使其与Oracle兼容。 select语句是普通香草SQL,可在任何数据库上使用。

^^^注意的另一件事。 如果ID字段是数字字段,则可能需要将其强制转换为CHAR,以便将其与“ Value”连接。

对于Sql Server,请考虑将UNPIVOT替代UNION:

SELECT id, value, colname
FROM #temp t
UNPIVOT (Value FOR ColName IN (value1,value2,value3)) as X

这也将返回列名称。 我不确定X的用途,但是您不能忽略它。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM