多行我們有一個表,它的形式是:單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。
多行我們有一個表,它的形式是:單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。
這個工程上的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)
給一個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不同),但它可能會加快一點。
你可以像這樣做,但它不漂亮:
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
對於SQL Server,考慮UNPIVOT作爲替代UNION:
SELECT id, value, colname
FROM #temp t
UNPIVOT (Value FOR ColName IN (value1,value2,value3)) as X
這也會返回列名稱。我不確定X被用於什麼,但是你不能把它放棄。
正如其他人所建議的,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
享受!
一些事後。
^^^在Oracle中,CTE語法可能有所不同。我只能在Teradata上運行它。您可以用臨時表替換它或修復語法以使其與Oracle兼容。 select語句是普通的vanilla SQL,可以在任何數據庫上工作。
^^^另一件要注意的事情。如果ID字段是數字,則可能需要將其轉換爲CHAR以將其與「值」連接起來。
對於Oracle(我在Teradata中運行它),CTE語法可能不同,但我只使用CTE提供測試數據,那些是1 2 3和4。實際的select語句是普通的vanilla SQL,它將在任何關係數據庫中使用。
您使用的是哪種數據庫服務器? – 2009-05-20 13:25:56
是1,2,3,4列還是數據值? – 2009-05-20 13:28:00
我能想到的最明智的方式是重新設計數據庫,使其規範化:) – 2009-05-20 13:55:32