2009-05-20 148 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,它將在任何關係數據庫中使用。