【问题标题】:Historical table with start and end dates and pivot具有开始和结束日期以及数据透视表的历史表
【发布时间】:2019-02-06 14:36:46
【问题描述】:

我有一张历史表。

条件:

min 从 date_asgn 开始的日期开始 start_cycle 在下一个日期之前的第二个结束周期。 只需要当天的最新日期,不管它在哪个角色下。

PKID    ID   CUSTID  ROLE      Date_ASGN
 1      45    4565   Primary   12/20/2018 3:12:24 PM
 2      45    4025   Secondary 12/20/2018 3:12:24 PM
 3      45    594    Primary   1/2/2019 4:09:58 PM

我的预期输出:

ID START_CYCLE          END_CYCLE          PRIMARY  SECONDARY  BACKUP
45  12/20/2018 3:12:24  1/2/2019 4:09:57   4565       4025      NULL
45  1/2/2019   4:09:58  12/31/9999         594        4025      NULL

我当前的 SQL。

SELECT
A.ID,
A.DATE_ASGN AS START_CYCLE,
CASE WHEN LEAD (A.DATE_ASGN ) OVER (PARTITION BY A.ID ORDER BY A.DATE_ASGN ) = TRUNC(A.DATE_ASGN ) THEN NULL 
ELSE LEAD (A.DATE_ASGN ) OVER (PARTITION BY A.ID ORDER BY A.DATE_ASGN ) - NUMTODSINTERVAL(1,'second')
END AS END_CYCLE,
'' AS [PRIMARY],
'' AS SECONDARY
'' AS [BACKUP]

FROM (SELECT * FROM (SELECT H.*,DENSE_RANK() OVER (PARTITION BY ID,TRUNC(H.DATE_ASGN) ORDER BY H.DATE_ASGN DESC,PK DESC) RNK
  FROM  H
  WHERE H.ID = 45
                          )
                          WHERE RNK = 1) A

输出:

 ID  START_CYCLE            END_CYCLE           PRIMARY  SECONDARY  BACKUP
 45   12/20/2018 3:12:24 PM 1/2/2019 4:09:57 PM  
 45   1/2/2019 4:09:58      12/31/9999

需要执行哪些其他步骤才能获得预期的输出。我正在考虑将我的 SQL 转换为 CTE 并从那里开始工作,但不知道从哪里开始。

【问题讨论】:

  • 如果在开始日期和结束日期之间有两个次要角色怎么办?或者,如果最后一行是次要角色怎么办?放在主要列和次要列中的内容背后的规则是什么?
  • @Boneist - 按照我的阅读方式,如果 DATE_ASGN 列中有三个(或四个等)不同的值,则在输出。我将输入数据视为分配的历史,将输出视为更完整的报告,说明在不同时间段内谁被分配了什么。 (显然,这就是我的答案中的解决方案所做的。)唯一的歧义是(ID, ROLE, DATE_ASGN) 中是否有重复项 - 我默默地假设该组合存在唯一约束。

标签: sql oracle date pivot common-table-expression


【解决方案1】:

您已经拥有解决方案的要素。因此,您应该不会很难理解下面的代码。请根据需要提出后续问题。

注意中间步骤,我称为 p 的 CTE - 当我们使用 pivot 运算符(在本例中为列 PKID)时,我们需要删除不需要的列,并且我放置了您的附加过滤器, where id = 45,在这个中间步骤中。

with
  h (pkid, id, custid, role, date_asgn) as (
    select 1, 45,  4565, 'Primary'  , to_date('12/20/2018 3:12:24 PM'
                                , 'mm/dd/yyyy hh:mi:ss AM') from dual union all
    select 2, 45,  4025, 'Secondary', to_date('12/20/2018 3:12:24 PM'
                                , 'mm/dd/yyyy hh:mi:ss AM') from dual union all
    select 3, 45,   594, 'Primary'  , to_date('1/2/2019 4:09:58 PM  '
                                , 'mm/dd/yyyy hh:mi:ss AM') from dual
  )
, p as (select id, custid, role, date_asgn from h where id = 45)
select id, date_asgn as start_cycle,
       lead(date_asgn, 1, date '9999-12-31') over (order by date_asgn) end_cycle,
       last_value(primary   ignore nulls)    over (order by date_asgn) primary,
       last_value(secondary ignore nulls)    over (order by date_asgn) secondary,
       last_value(backup    ignore nulls)    over (order by date_asgn) backup
from   p
pivot  (max(custid) for role in ('Primary' primary, 'Secondary' secondary,
                                                       'Backup' backup))
;

ID START_CYCLE            END_CYCLE                 PRIMARY  SECONDARY     BACKUP
-- ---------------------- ---------------------- ---------- ---------- ----------
45 12/20/2018 03:12:24 PM 01/02/2019 04:09:58 PM       4565       4025           
45 01/02/2019 04:09:58 PM 12/31/9999 12:00:00 AM        594       4025   

【讨论】:

    【解决方案2】:

    您是否只想按iddate_asn 的日期部分聚合?

    select id, min(date_asn) as start_cycle, max(date_asn) as end_cycle,
           max(case when role = 'Primary' then custid end) as primary,
           max(case when role = 'Secondary' then custid end) as secondary,
           max(case when role = 'Backup' then custid end) as backup
    from t
    group by id, trunc(date_asn);
    

    如果你想用最近的非NULL 次要填充secondary

    select id, min(date_asn) as start_cycle, max(date_asn) as end_cycle,
           max(case when role = 'Primary' then custid end) as primary,
           lag(max(case when role = 'Secondary' then custid end) ignore nulls) over (partition by id order by min(date_asn)) as secondary,
           max(case when role = 'Backup' then custid end) as backup
    from t
    group by id, trunc(date_asn);
    

    【讨论】:

      猜你喜欢
      • 2019-07-07
      • 2015-06-17
      • 1970-01-01
      • 1970-01-01
      • 2014-03-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多