Oracle - 根据日期排列行

时间:2017-03-12 16:56:07

标签: sql oracle oracle11g

来源数据:

+----+-----------------+------+---------------+---------------+
| ID | AUTH_ROLE_NM    | ROLE | ST_DT         | END_DT        |
+----+-----------------+------+---------------+---------------+
| 1  | channel_manager | A    | 01.01.2017 00 | 01.01.2017 00 |
+----+-----------------+------+---------------+---------------+
| 1  | channel_manager | C    | 01.01.2017 01 | 01.01.2999 00 |
+----+-----------------+------+---------------+---------------+
| 2  | channel_manager | D    | 01.01.2017 00 | 01.01.2999 00 |
+----+-----------------+------+---------------+---------------+
| 1  | market manager  | B    | 01.01.2017 00 | 01.01.2999 00 |
+----+-----------------+------+---------------+---------------+
| 2  | market manager  | E    | 01.01.2017 02 | 01.01.2999 00 |
+----+-----------------+------+---------------+---------------+

目标数据

+----+-----------+-----------+---------------+---------------+
| ID | chnl_mngr | mrkt mngr | ST_DT         | END_DT        |
+----+-----------+-----------+---------------+---------------+
| 1  | A         | B         | 01.01.2017 00 | 01.01.2017 00 |
+----+-----------+-----------+---------------+---------------+
| 1  | C         | B         | 01.01.2017 01 | 01.01.2999 00 |
+----+-----------+-----------+---------------+---------------+
| 2  | D         |           | 01.01.2017 00 | 01.01.2999 00 |
+----+-----------+-----------+---------------+---------------+
| 2  | D         | E         | 01.01.2017 02 | 01.01.2999 00 |
+----+-----------+-----------+---------------+---------------+

说明,在输出集中,

  • 第1行 - 对于ID 1,A为通道mgr,B为mktmgr为日期范围
  • 第2行 - 对于ID 1,C为通道mgr,B为日期范围的m为mktmgr
  • 第3行 - 对于ID 2 D是通道mgr而日期范围没有mktmgr
  • 第4行 - 对于ID 2,A为通道mgr,E为mktmgr为日期范围

如何实现目标集?

select id,
st_dt,
END_dt,
max(case when auth_role_name = 'channel_manager' then hotel_role_name end) as channel_manager,
max(case when auth_role_name = 'market manager' then hotel_role_name end) as market_manager 
from source
group by 
id,
st_dt,
END_dt

我尝试过这样的事情,但我坚持使用日期范围。

1 个答案:

答案 0 :(得分:1)

希望,我理解你的问题。

请查看下面的查询可以提供帮助。

    with data as
(select 1 as ID ,'channel_manager'as AUTH_ROLE_NM    ,'A'as ROLE ,'01.01.2017 00'as ST_DT  ,'01.01.2017 00'as END_DT  from dual  
 union
 select 1 as ID ,'channel_manager'as AUTH_ROLE_NM    ,'C'as ROLE ,'01.01.2017 01'as ST_DT  ,'01.01.2999 00'as END_DT  from dual    
 union
 select 2 as ID ,'channel_manager'as AUTH_ROLE_NM    ,'D'as ROLE ,'01.01.2017 00'as ST_DT  ,'01.01.2999 00'as END_DT  from dual   
 union
 select 1 as ID ,'market manager'as AUTH_ROLE_NM     ,'B'as ROLE ,'01.01.2017 00'as ST_DT  ,'01.01.2999 00'as END_DT   from dual    
 union
 select 2 as ID ,'market manager'as AUTH_ROLE_NM     ,'E'as ROLE ,'01.01.2017 02'as ST_DT  ,'01.01.2999 00'as END_DT    from dual  
 )
select a.id , a.role as chnl_mngr , 
case when  (to_date(b.ST_DT,'dd:mm:rrrr hh24') <=to_date(a.ST_DT,'dd:mm:rrrr hh24') and a.id = b.id)
or (b.ST_DT<=a.END_DT and a.id = b.id)
then
b.role else null end as mrkt_mngr ,
case when a.id = b.id and b.ST_DT>=a.ST_DT then b.ST_DT else  a.ST_DT end ST_DT ,
--b.ST_DT ,
b.END_DT  
from  data  a 
left outer join (select id , role ,  ST_DT , END_DT 
from  data where AUTH_ROLE_NM = 'market manager' ) b
on a.id = b.id
or to_date(a.ST_DT,'dd:mm:rrrr hh24') >= to_date(b.ST_DT,'dd:mm:rrrr hh24') 
where AUTH_ROLE_NM = 'channel_manager'
order by 1
;

更新的查询:根据“如何将第三个输出行设为2|D| | 01.01.2017 00 | 01.01.2017 02”更新查询

 with data as
(select 1 as ID ,'channel_manager'as AUTH_ROLE_NM    ,'A'as ROLE ,'01.01.2017 00'as ST_DT  ,'01.01.2017 00'as END_DT  from dual  
 union
 select 1 as ID ,'channel_manager'as AUTH_ROLE_NM    ,'C'as ROLE ,'01.01.2017 01'as ST_DT  ,'01.01.2999 00'as END_DT  from dual    
 union
 select 2 as ID ,'channel_manager'as AUTH_ROLE_NM    ,'D'as ROLE ,'01.01.2017 00'as ST_DT  ,'01.01.2999 00'as END_DT  from dual   
 union
 select 1 as ID ,'market manager'as AUTH_ROLE_NM     ,'B'as ROLE ,'01.01.2017 00'as ST_DT  ,'01.01.2999 00'as END_DT   from dual    
 union
 select 2 as ID ,'market manager'as AUTH_ROLE_NM     ,'E'as ROLE ,'01.01.2017 02'as ST_DT  ,'01.01.2999 00'as END_DT    from dual  
 )
select a.id , a.role as chnl_mngr , 
case when  (to_date(b.ST_DT,'dd:mm:rrrr hh24') <=to_date(a.ST_DT,'dd:mm:rrrr hh24') and a.id = b.id)
or (b.ST_DT<=a.END_DT and a.id = b.id)
then
b.role else null end as mrkt_mngr ,
case when a.id = b.id and b.ST_DT>=a.ST_DT then b.ST_DT else  a.ST_DT end ST_DT ,
--b.ST_DT ,
case when 
  lead(b.ST_DT) over(partition by a.id order by a.ST_DT )>= to_date(a.ST_DT)
then lead(b.ST_DT) over(partition by a.id order by a.ST_DT ) else  b.END_DT   end END_DT
from  data  a 
left outer join (select id , role ,  ST_DT , END_DT 
from  data where AUTH_ROLE_NM = 'market manager' ) b
on a.id = b.id
or to_date(a.ST_DT,'dd:mm:rrrr hh24') >= to_date(b.ST_DT,'dd:mm:rrrr hh24') 
where AUTH_ROLE_NM = 'channel_manager'
order by 1
;