user8467219
user8467219

Reputation:

Conditional Analytic Function

Work:

,MAX(CASE WHEN MAX(HIST)
      AND workid IS NOT NULL 
     AND ROLE = 'red' 
       THEN 'ASSIGNED'
         ELSE 'UNASSIGNED'
         END)
            OVER (PARTITION BY id) AS ASSIGNED 

Criteria:

Partition By ID

Look at last entry from each ID, utilizing the PKHistid column

If Role = Red and Workid IS NOT NULL from the last entry for each ID

Then Assigned

Else Unassigned

Table:

PKHistid    ID    Role       Entry_Date    Workid
 1          101    Red       1/1/17         201
 2          101    Yellow    1/2/17         201
 3          102    Yellow    5/1/17        (Null)
 4          102    Red       6/1/17         202
 5          103    Red       7/1/17         202
 6          103    Red       7/5/17         202

Expected Results: (New Column Assigned_Status)

PKHistid    ID    Role       Entry_Date    Workid    *Assigned_Status
 1          101    Red       1/1/17         201         Unassigned
 2          101    Yellow    1/2/17         201         Unassigned
 3          102    Yellow    5/1/17        (Null)       Assigned
 4          102    Red       6/1/17         202         Assigned
 5          103    Red       7/1/17         202         Assigned
 6          103    Red       7/5/17         202         Assigned

Upvotes: 0

Views: 1105

Answers (1)

user5683823
user5683823

Reputation:

Is this "instead of" your earlier question (also posted today), or is it "in addition to" it? If it is "in addition to", note that you can do both things in the same query.

Here you need a case expression to create the additional column. In the case expression, the condition uses an analytic function. I prefer the analytic version of the LAST function (which, unfortunately, many developers don't seem to know and use). Please read the Oracle documentation for it if it is not familiar to you.

Note that analytic functions can't be nested; but there is absolutely no prohibition against using analytic functions in case expressions. I often see solutions where the analytic function is called in a subquery, and then further processing (such as case expressions using the result from the analytic functions) is done in an outer query. Unnecessary layering!

with
  inputs ( pkhistid, id, role, entry_date, workid) as (
    select 1, 101, 'Red'   , to_date('1/1/17', 'mm/dd/rr'), 201  from dual union all
    select 2, 101, 'Yellow', to_date('1/2/17', 'mm/dd/rr'), 201  from dual union all
    select 3, 102, 'Yellow', to_date('5/1/17', 'mm/dd/rr'), null from dual union all
    select 4, 102, 'Red'   , to_date('6/1/17', 'mm/dd/rr'), 202  from dual union all
    select 5, 103, 'Red'   , to_date('7/1/17', 'mm/dd/rr'), 202  from dual union all
    select 6, 103, 'Red'   , to_date('7/5/17', 'mm/dd/rr'), 202  from dual
  )
-- End of simulated inputs (for testing only, not part of the solution).
-- SQL query begins BELOW THIS LINE. Use your actual table and column names.
select   pkhistid, id, role, entry_date, workid,
         case when max(role)   keep (dense_rank last order by pkhistid)
                               over (partition by id) = 'Red'
                   and
                   max(workid) keep (dense_rank last order by pkhistid)
                               over (partition by id) is not null
              then 'Assigned'
              else 'Unassigned' end as assigned_status
from     inputs
order by id, pkhistid -- If needed
;

  PKHISTID         ID ROLE   ENTRY_DATE     WORKID ASSIGNED_STATUS
---------- ---------- ------ ---------- ---------- ---------------
         1        101 Red    01/01/17          201 Unassigned
         2        101 Yellow 01/02/17          201 Unassigned
         3        102 Yellow 05/01/17              Assigned  
         4        102 Red    06/01/17          202 Assigned  
         5        103 Red    07/01/17          202 Assigned  
         6        103 Red    07/05/17          202 Assigned  

Upvotes: 2

Related Questions