2009-05-20 88 views
5

多行我们有一个表,它的形式是:单SQL SELECT返回从一个表行

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

我们需要转换成以下。

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

在一个SELECT语句(即没有UNIONs)中有这样做的巧妙方法吗?列名称Value1,Value2和Value3是固定的并且是常量。

数据库是oracle 9i。

+0

您使用的是哪种数据库服务器? – 2009-05-20 13:25:56

+0

是1,2,3,4列还是数据值? – 2009-05-20 13:28:00

+1

我能想到的最明智的方式是重新设计数据库,使其规范化:) – 2009-05-20 13:55:32

回答

3

这个工程上的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来说更为通用一些。 (使用联合来生成行可移植到其他DB)

9

给一个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应该HOPEFULLY不同),但它可能会加快一点。

2

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

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 
2

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 
0

如果您使用的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 
-1

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

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

这也会返回列名称。我不确定X被用于什么,但是你不能把它放弃。

0

正如其他人所建议的,UNION ALL可能是SQL中最好的选择。您可能还想考虑在前端处理这些问题,具体取决于您的具体要求。

-1

试试这个:

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 

享受!

一些事后。

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

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

0

对于Oracle(我在Teradata中运行它),CTE语法可能不同,但我只使用CTE提供测试数据,那些是1 2 3和4。实际的select语句是普通的vanilla SQL,它将在任何关系数据库中使用。