显示按列名分隔的额外行(有条件地)

时间:2015-09-11 19:00:58

标签: sql oracle view oracle11g

我有一张这样的表:

initial   confirmatory  confirmatory1  confirmatory2  confirmatory3
3.4       true          3.6            4.9            7.4
2.1       false         null           null           null

我想生成这样的数据库视图:

initial  confirmatory_n  confirmatory_value
3.4      1               3.6
3.4      2               4.9
3.4      3               7.4
2.1      null            2.1

对于confirmatory为false的行,我需要显示第1行。对于confirmatory为true的行,我需要在三个不同的行中显示3次数据,并使用额外的列标识显示的值。

我一直在搜索,但似乎无法找到相关结果。在尝试展示confirmatory_n时,我总是陷入困境。所以,我真的没有一个没有工作的sql样本,因为我觉得我离我很远。但是,我确实创建了一个可能有帮助的sqlfiddle。任何帮助都会很棒。

我使用的是Oracle 11g。

4 个答案:

答案 0 :(得分:2)

另一个UNPIVOT解决方案:

WITH src ("INITIAL", confirmatory, confirmatory1, confirmatory2, confirmatory3) as (
    SELECT 3.4, 'true', 3.6, 4.9, 7.4 FROM DUAL UNION ALL
    SELECT 2.1, 'false', NULL, NULL, NULL FROM DUAL
), dta as (
select "INITIAL"
     , case upper(confirmatory) when 'FALSE' then "INITIAL" end confirmatory
     , confirmatory1
     , confirmatory2
     , confirmatory3
  from src
)
select *
 from dta
 unpivot (confirmatory_value
     FOR confirmatory_n IN (CONFIRMATORY  AS null,
                            CONFIRMATORY1 AS 1,
                            CONFIRMATORY2 AS 2,
                            CONFIRMATORY3 AS 3));

答案 1 :(得分:1)

使用union all

select initial_value, 1 as confirmatory_n, confirmatory1 as confirmatory
from results t
where confirmatory = 1
union all
select initial_value, 2 as confirmatory_n, confirmatory2 as confirmatory
from results t
where confirmatory = 1
union all
select initial_value, 3 as confirmatory_n, confirmatory3 as confirmatory
from results t
where confirmatory = 1
union all
select initial_value, null as confirmatory_n, initial_value
from results t
where confirmatory = 0;

SQL小提琴是here。 如果您的表非常大并且性能是一个问题,那么还有其他方法只扫描一次表。但是,这种方法通常就足够了。

答案 2 :(得分:1)

UNPIVOT解决方案

WITH src ("INITIAL", confirmatory, confirmatory1, confirmatory2, confirmatory3) as (
    SELECT 3.4, 'true', 3.6, 4.9, 7.4 FROM DUAL UNION ALL
    SELECT 2.1, 'false', NULL, NULL, NULL FROM DUAL
)
SELECT
    "INITIAL",
    confirmatory_n,
    confirmatory_value
FROM (
    SELECT
        "INITIAL",
        CASE WHEN confirmatory_value IS NOT NULL THEN confirmatory_n END confirmatory_n,
        CASE WHEN confirmatory_value IS NOT NULL THEN confirmatory_value ELSE "INITIAL" END confirmatory_value
    FROM
        src
        UNPIVOT INCLUDE NULLS (
            confirmatory_value FOR confirmatory_n IN (confirmatory1 AS 1, confirmatory2 AS 2, confirmatory3 AS 3)
        )
    )
GROUP BY
    "INITIAL",
    confirmatory_n,
    confirmatory_value
ORDER BY
    confirmatory_n;

答案 3 :(得分:0)

这可能不是最有效的解决方案(特别是 n 的任意值),但您可以编写一系列UNION选项来完成此任务。适用于Oracle 12c。

编辑:编辑以适合您的小提琴。

Edit2:UNION ALL性能更高。我的解决方案需要union过滤掉确认错误的重复行。 union all解决方案会更高效。

select initial_value,
    case when (confirmatory = 1 and confirmatory1 is not null) then '1' else null end confirmatory_n, 
    case when (confirmatory = 1 and confirmatory1 is not null) then confirmatory1 else initial_value end confirmatory_value
from results
UNION 
select initial_value,
    case when (confirmatory = 1 and confirmatory2 is not null) then '2' else null end confirmatory_n, 
    case when (confirmatory = 1 and confirmatory2 is not null) then confirmatory2 else initial_value end confirmatory_value
from results
UNION 
select initial_value,
    case when (confirmatory = 1 and confirmatory3 is not null) then '3' else null end confirmatory_n, 
    case when (confirmatory = 1 and confirmatory3 is not null) then confirmatory3 else initial_value end confirmatory_value
from results