动态创建行到列(Oracle)

时间:2016-10-20 13:28:39

标签: sql oracle plsql

我有2张桌子。表用户存储如下用户的信息。

**user_id      user_name**
1            naveen
2            richard
3            reddy

另一个表User_activity。存储用户计划的详细信息。

**user_id      Activity   date**
1            holiday   1-aug-2016
2            working   1-aug-2016
3            training  1-aug-2016
1            working   2-aug-2016
2            working   2-aug-2016
3            working   2-aug-2016

现在我需要以下面的格式创建报告。请帮我写一个相同的查询。

**Date         naveen        Richard     reddy**
1-aug-2016   holiday       working     training
2-aug-2016   working       working     working

2 个答案:

答案 0 :(得分:0)

无法做到这一点。 (PIVOT_XML除外)。

长话短说: 当您执行查询时,Oracle将向您发送列及其数据类型的描述。甚至在它实际触及任何数据之前。

Oracle使用生产者 - 消费者原则,因此在评估数据时会将数据发送到客户端 - 结果集不会在服务器端缓冲。

所以你的要求违背了这个原则。如果列数取决于数据内容,则Oracle必须动态更改结果集参数 - 这是不可能的。

PIVOT_XML是一个例外,因为它只生成一个CLOB列。

答案 1 :(得分:0)

您可以尝试稍微不同的东西,使用包含数据串联的单个列构建输出。 假设每个用户每天都有一个活动,你可以试试这样的事情:

with users(user_id, user_name) as
(
    select 1, 'naveen' from dual union all
    select 2, 'richard' from dual union all
    select 3, 'reddy' from dual
),
user_activity( user_id, Activity, activity_date) as
(
    select 1, 'holiday'  , date '2016-08-01' from dual union all
    select 2, 'working'  , date '2016-08-01' from dual union all
    select 3, 'training' , date '2016-08-01' from dual union all
    select 1, 'working'  , date '2016-08-02' from dual union all
    select 2, 'working'  , date '2016-08-02' from dual union all
    select 3, 'working'  , date '2016-08-02' from dual
)
select rpad('Date', 16, ' ') || ',' || listagg(rpad(user_name, 16, ' '), ',') within group (order by user_id)
from users
union all
select rpad(to_char(activity_date, 'yyyy-mm-dd'),16, ' ') || ',' || listagg(rpad(activity, 16, ' '), ',') within group (order by user_id)
from users 
      inner join user_activity using(user_id)
group by activity_date

结果:

RPAD('DATE',16,'')||','||LISTAGG(RPAD(USER_NAME,16,''),',')WITHINGROUP(ORDERBYUS
--------------------------------------------------------------------------------
Date            ,naveen          ,richard         ,reddy
2016-08-01      ,holiday         ,working         ,training
2016-08-02      ,working         ,working         ,working

如果我添加第四个男人:

RPAD('DATE',16,'')||','||LISTAGG(RPAD(USER_NAME,16,''),',')WITHINGROUP(ORDERBYUSER_ID)
----------------------------------------------------------------------------------------------------
Date            ,naveen          ,richard         ,reddy           ,Fourth Man
2016-08-01      ,holiday         ,working         ,training        ,training
2016-08-02      ,working         ,working         ,working         ,working