多行我们有一个表,它的形式是:单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