我们有一个表,该表具有以下形式:

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

我们需要变换成此。

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

是否有一个SELECT语句这样做(即不联合)的一个聪明的办法?列名称值1,值和值3是固定的,是恒定的。

在数据库为Oracle 9i中。

有帮助吗?

解决方案

此适用于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中有递归查询?无论如何,我敢肯定它具有箱支撑,所以即使它没有递归查询,你可以做“(从双工会选择1所有从双联盟选择2个全部来自双选3)OFS”来代替。滥用递归查询是甲骨文公司的中普通一点。 (使用工会,以产生行是移植到其他的DB,虽然)

其他提示

给一个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应该有希望是不同的)任何区别,但它可能会加速它一点。

您可以像这样做,但它不漂亮:

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

Unioning三个select语句应该做的伎俩:

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

如果您正在使用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语法可以是用于不同的Oracle(我跑它在Teradata的),但我只用CTE以提供测试数据,那些1 2 3和4可以使用临时表来代替。实际的select语句是普通的香草SQL,它会在任何关系型数据库。

对于SQL Server,考虑UNPIVOT作为替代UNION:

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

这将返回列名以及。我不能确定什么X的用途,但你不能离开它了。

尝试这种情况:

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,以便与“价值”来连接它。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top