令人费解的差距和孤岛 ORACLE SQL
Posted
技术标签:
【中文标题】令人费解的差距和孤岛 ORACLE SQL【英文标题】:Perplexing Gaps and Island ORACLE SQL 【发布时间】:2014-06-09 20:44:00 【问题描述】:我需要按照TSK和ACTCODE将以下数据重新排序到Oracle SQL中自己的孤岛中,并按日期排序。新数据将显示 TSK,连续组的第一个实例的 STARTDATE,连续组的最后一个实例的 ENDDATE,其余数据字段都与连续组的最后一个实例(MAX ENDDATE)有关。有没有办法在存储过程之外做到这一点?
感谢您的帮助!
示例数据集:
(之前的数据)
(Fields) TSK STARTDATE ENDDATE ACTCODE DPTCODE TSKCODE OPERID
1 A 01/06/2014 01/06/2014 2 1587 1584 I511191
2 A 01/06/2014 01/06/2014 11 1587 1583 I511191
3 A 01/08/2014 01/08/2014 2 1587 1584 CLARKC
4 A 01/16/2014 01/16/2014 2 1587 1585 MENDUA
(之后的数据)
(Fields) TSK STARTDATE ENDDATE ACTCODE DPTCODE TSKCODE OPERID
1 A 01/06/2014 01/06/2014 2 1587 1584 I511191
2 A 01/06/2014 01/06/2014 11 1587 1583 I511191
3 A 01/08/2014 01/16/2014 2 1587 1585 MENDUA
【问题讨论】:
“重新排序”是什么意思?表记录(通常)不按任何特定顺序存储。 我的意思是按日期、tsk 和 actcode 重新排序 【参考方案1】:基本的“间隙和孤岛”过程是通过获取两个连续值之间的差异来识别组。在您的情况下,您可以这样做来识别组:
select t.*,
(row_number() over (order by fields) -
row_number() over (partition by tsk, actcode order by fields)
) as grp
from table t
要得到你想要的只是更多的工作和聚合:
select min(fields) as fields, min(startdate) as startdate, tsk, max(enddate) as enddate, actcode,
max(DPTCODE) keep (dense_rank first order by enddate desc),
max(TSKCODE) keep (dense_rank first order by enddate desc),
max(OPERID) keep (dense_rank first order by enddate desc)
from (select t.*,
(row_number() over (order by fields) -
row_number() over (partition by tsk, actcode order by fields)
) as grp
from table t
) t
group by grp, tsk, actcode;
【讨论】:
【参考方案2】:什么版本的甲骨文?如果是最近的,将支持 OLAP 功能(有点简化):
select min(startdate) as startdate
, max(enddate) as enddate
, actcode
, grp
from (
select startdate, enddate, actcode
, row_number() over (order by startdate)
- row_number() over (partition by actcode
order by startdate) as grp
from T
) as A
group by actcode, grp
【讨论】:
嗨 Lennart,它是 Oracle 10.5。谢谢。【参考方案3】:感谢戈登的回复!我想我一直都错过了密集等级公式。无论如何,与我的程序完美配合。非常感谢大家的帮助。
with testsomething as (
select distinct tskid,pidate,operid,starttime,to_date(substr(effdate,5,2)||'/'||substr(effdate,7,2)||'/'||substr(effdate,1,4),'MM/DD/YYYY') as serveffdate,to_date(substr(pidate,5,2)||'/'||substr(pidate,7,2)||'/'||substr(pidate,1,4)||' '||
substr(lpad(starttime,8,0),1,2)||':'||substr(lpad(starttime,8,0),3,2)||':'
||substr(lpad(starttime,8,0),5,2), 'MM/DD/YYYY HH24:MI:SS') as startdatetime,
to_date(substr(pidate,5,2)||'/'||substr(pidate,7,2)||'/'||substr(pidate,1,4)||' '||
substr(lpad(starttime,8,0),1,2)||':'||substr(lpad(starttime,8,0),3,2)||':'
||substr(lpad(starttime,8,0),5,2), 'MM/DD/YYYY HH24:MI:SS') as enddatetime,
endtime, dptcode,actcode,tskcode from tskhist where tskid in (select tskid from comptsk where compdate between '20140501' and '20140530') and dptcode=1587
order by tskid,pidate, starttime asc)
--,lastoperid as
--(select distinct tskid,actcode,operid,max(enddatetime) from testsomething group by tskid,operid,actcode)
,q AS
(
SELECT tskid,dptcode,actcode,enddatetime,startdatetime,tskcode,serveffdate,operid,
ROW_NUMBER() OVER (PARTITION BY tskid, actcode ORDER BY startdatetime) AS rnd,
ROW_NUMBER() OVER (PARTITION BY tskid ORDER BY startdatetime) AS rn
FROM testsomething
)
,q2 as (
select min(startdatetime) as startdatetime,max(enddatetime) as enddatetime,tskid,actcode,dptcode,tskcode,serveffdate,max(OPERID) keep (dense_rank first order by enddatetime desc) as operid
from q
GROUP BY
tskid,actcode,dptcode,tskcode,serveffdate,(rnd - rn) order by tskid,actcode,startdatetime)
select distinct startdatetime, enddatetime,serveffdate,operid,a.tskid,a.actcode,(case when a.actcode=0 then 'NoAction' else b.actdesc end) as actdesc,a.dptcode,c.dptdesc,a.tskcode,d.tskdesc
from q2 a, acttype b, dpt c, tsktype d
where a.actcode=b.actcode(+) and a.dptcode=c.dptcode(+) and a.tskcode=d.tskcode(+)
order by tskid, actcode,startdatetime asc
【讨论】:
以上是关于令人费解的差距和孤岛 ORACLE SQL的主要内容,如果未能解决你的问题,请参考以下文章