单SQL SELECT从一个表行返回多个行
题
我们有一个表,该表具有以下形式:
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,以便与“价值”来连接它。