令人费解的差距和孤岛 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的主要内容,如果未能解决你的问题,请参考以下文章

SQL Server:寻找就业差距——孤岛和差距问题

差距和孤岛 - Microsoft Access

差距和孤岛问题是不是有正式定义?如果是这样,这个问题是不是满足它?

SQL Server - 计算会话数 - 差距和孤岛

具有开始和结束日期的差距和孤岛(有效期)

使用差距和孤岛知识找到最长时间不改变就业(SQL)