Oracle将多个列合并为一个

时间:2017-06-16 19:49:36

标签: sql oracle row transform

我对Oracle Sql有疑问,

如果我有一个名为A的数据,有8列:

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<div id="main_topbar">Main Topbar</div>
<div id="main_content">
  <div id="content">
    Bla sdlkkgj sa;lkfjj a;lkgj a;lkgj ja;lkg jal;kg jdlgkjd lgkjdf lgjhdfjhdgfb mfnbvufhfkkhkjhgjh ggjhg <br>bla<br>bladiebla<br>Bla<br>bla<br>bladiebla<br>Bla<br>bla<br>bladiebla<br>Bla<br>bla<br>bladiebla<br>Bla<br>bla<br>bladiebla<br>Bla<br>bla<br>bladiebla<br>Bla<br>bla<br>bladiebla<br>Bla<br>bla<br>bladiebla<br>Bla<br>bla<br>bladiebla
  </div>
</div>

我可以将它转换为表格B:

Spot| ID |Sunday|Monday|Tuesday|Wednesday|Thursday|Friday|Saturday 
-------------------------------------------------------------------------
   A| 1  | 0.1  |0.15  | ...........................................
-------------------------------------------------------------------------
   A| 2  | 0.2  |0.2   | ...........................................
-------------------------------------------------------------------------
   A| 3  | 0.3  |0.25  | ...........................................
-------------------------------------------------------------------------
   A| 4  | 0.4  |0.4   | ...........................................
-------------------------------------------------------------------------

将列(星期日到星期六)组合到名为“星期几”的新列

我该怎么办呢?谢谢!

2 个答案:

答案 0 :(得分:1)

基本上有三种方法可以做到这一点,每种方法各有优缺点。 (可能有三个以上,这些是我所知道的。)

第一种方法使用UNION ALL,它适用于小型表(性能并不重要)。它适用于任何版本的Oracle。它是这样的:

select spot, 1 as day_of_week, id, sunday  as value from a union all
select spot, 2               , id, monday           from a union all
.......

这是低效的,因为基表(A)被读取七次,UNION ALL的每个分支被读取一次。有些行可能会被缓存,所以也许它不是完全I / O时间乘以7,但它仍然效率低下。

自Oracle 11.1起,我们已经有PIVOTUNPIVOT。你需要透视,像这样:

select  spot, day_of_week, id, value
from    a
unpivot ( value for day_of_week in ( sunday as 1, monday as 2, .... ) )
;

这会更快;目前尚不清楚Oracle是如何实现这一目标的,它可能仍然会执行UNION ALL,但它是一个智能的 - 其中同一行使用了七次,而不是从磁盘重复读取。当然,缺点是它在旧版本的Oracle中不可用。

第三种方法使用笛卡尔连接。它可以快速工作,并且可以在所有版本中使用。

select a.spot, h.day_of_week, id,
       case h.day_of_week when 1 then sunday
                          when 2 then monday
                          ..................
                          when 7 then saturday
       end  as value
from   a 
       cross join
       ( select level as day_of_week from dual connect by level <= 7) h
;

此解决方案中的子查询h可能看起来很花哨,但它只是创建一个内嵌视图h,其中包含一列day_of_week,其值为1到7它可以用任何其他方式创建,这只是一个快速(和常见)的方式。

答案 1 :(得分:1)

您可以使用UNPIVOT

Oracle安装程序

CREATE TABLE your_table ( spot, id, sunday, monday, tuesday, wednesday, thursday, friday, saturday ) AS
  SELECT 'A', 1, 0.1, 0.15, 0.2, 0.25, 0.3, 0.35, 0.4 FROM DUAL UNION ALL
  SELECT 'A', 2, 0.15, 0.2, 0.25, 0.3, 0.35, 0.4, 0.45 FROM DUAL UNION ALL
  SELECT 'A', 3, 0.2, 0.25, 0.3, 0.35, 0.4, 0.45, 0.5 FROM DUAL;

<强>查询

SELECT *
FROM   your_table
UNPIVOT ( Value FOR Day_of_week IN (
  sunday    AS 1,
  monday    AS 2,
  tuesday   AS 3,
  wednesday AS 4,
  thursday  AS 5,
  friday    AS 6,
  saturday  AS 7
 ) );

<强>输出

S ID DAY_OF_WEEK VALUE
- -- ----------- -----
A  1           1    .1
A  1           2   .15
A  1           3    .2
A  1           4   .25
A  1           5    .3
A  1           6   .35
A  1           7    .4
A  2           1   .15
A  2           2    .2
A  2           3   .25
A  2           4    .3
A  2           5   .35
A  2           6    .4
A  2           7   .45
A  3           1    .2
A  3           2   .25
A  3           3    .3
A  3           4   .35
A  3           5    .4
A  3           6   .45
A  3           7    .5