在现有查询中包含listagg

时间:2017-12-01 20:11:35

标签: sql oracle


我有一个包含两列DETAIL_FROM和DETAIL_TO的表
From和To可以是Null或包含来自' A'到了'

  • 如果FROM:NULL和TO:NULL,则返回所有值:A,B,C,D
  • 如果FROM:NULL和TO:value_1则返回值为value_1(包括value_1)的所有值
  • 如果FROM:value2和TO:NULL则返回value2之后的所有值(包括value_2)
  • 如果FROM:value3和TO:value4则返回value_3和value_4之间的所有值

此外,我在两个表之间有一个主 - 细节关系 我想检查每一行主人是否都有包含C值的详细信息

我的查询是

With TBL_A as (
select 'A' as Type_Id from dual union all
select 'B' as Type_Id from dual union all
select 'C' as Type_Id from dual union all
select 'D' as Type_Id from dual
), TBL_B as (
select 1 as Master from dual union all
select 2 as Master from dual union all
select 3 as Master from dual union all
select 4 as Master from dual union all
select 5 as Master from dual  union all
select 6 as Master from dual        
), TBL_C as (
select 1 as Master,  '08' NUM,  'A' DETAIL_FROM ,  'D' DETAIL_TO from dual union all
select 2 as Master,  '08' NUM,  NULL DETAIL_FROM , 'D' DETAIL_TO from dual union all
select 3 as Master,  '08' NUM,  'A' DETAIL_FROM ,  'B' DETAIL_TO from dual union all
select 5 as Master,  '08' NUM,  'B' DETAIL_FROM ,  NULL DETAIL_TO from dual union all
select 5 as Master,  '08' NUM,  'A' DETAIL_FROM ,  'B' DETAIL_TO from dual 
)
select B.Master,  CASE WHEN C.NUM IS NULL THEN 'N' ELSE 'Y' END c_exists
from TBL_B B, TBL_C C
WHERE B.Master = C.Master (+)
AND C.NUM (+) = '08'
AND 'C' IN (SELECT Type_Id  
                   FROM TBL_A 
                 WHERE Type_Id >= NVL(C.DETAIL_FROM,Type_Id)
                    AND Type_Id <= NVL(C.DETAIL_TO,Type_Id))
ORDER BY B.Master;

输出:

|MASTER | C_EXISTS |
| 1     | Y        |
| 2     | Y        |
| 4     | N        |
| 5     | Y        |
| 6     | N        |

你能帮我解决一下使用listag重新计算datail_from的值吗? 示例输出:

|MASTER | TYPE_LIST | C_EXISTS |
| 1     | A,B,C,D   | Y        |
| 2     | A,B,C,D   | Y        |
| 4     | NULL      | N        |
| 5     | B,C,D     | Y        |
| 6     | A,B       | N        |

提前致谢

1 个答案:

答案 0 :(得分:0)

怎么样

with
  tbl_a as (
    select 'A' as type_id from dual union all
    select 'B' as type_id from dual union all
    select 'C' as type_id from dual union all
    select 'D' as type_id from dual),
 tbl_b as (
    select 1 as master from dual union all
    select 2 as master from dual union all
    select 3 as master from dual union all
    select 4 as master from dual union all
    select 5 as master from dual  union all
    select 6 as master from dual),
  tbl_c as (
    select 1 as master, '08' num, 'A' detail_from , 'D' detail_to from dual union all
    select 2 as master, '08' num, null detail_from , 'D' detail_to from dual union all
    select 3 as master, '08' num, 'A' detail_from , 'B' detail_to from dual union all
    select 5 as master, '08' num, 'B' detail_from , null detail_to from dual union all
    select 6 as master, '08' num, 'A' detail_from , 'B' detail_to from dual)
select tb.Master, max(case ta.type_id when 'C' then 'Y' else 'N' end) c_exists,
       listagg(ta.type_id,',') within group (order by tb.master) type_list
from tbl_b tb
left outer join tbl_c tc on tc.master = tb.master and tc.num = '08'
left outer join tbl_a ta on tb.master = tc.master and ta.type_id >= nvl(tc.detail_from, ta.type_id) and ta.type_id <= nvl(tc.detail_to, ta.type_id)
group by tb.master
order by tb.master;