Home > Software design >  How do I insert the missing rows
How do I insert the missing rows

Time:08-07

I currently have a table like this:

FK_ID Name Updated_Date
1 PLANNED [Some Date]
1 DOING [Some Date]
2 PLANNED [Some Date]
2 DOING [Some Date]
2 DONE [Some Date]
3 PLANNED [Some Date]

The problem I'm having is I'd like to insert all missing PLANNED, DOING, DONE for every set of FK_ID's into the table so the result would be

FK_ID Name Updated_Date
1 PLANNED [Some Date]
1 DOING [Some Date]
1 DONE [Blank]
2 PLANNED [Some Date]
2 DOING [Some Date]
2 DONE [Some Date]
3 PLANNED [Some Date]
3 DOING [Blank]
3 DONE [Blank]

I had the idea to create a table, although I'm sure a temp table would be fine that would just be

Name
PLANNED
DOING
DONE

and then do something with OUTER LEFT JOIN and/or NOT IN's but I'm not getting what I'm looking for. I'm thinking I need to have a query with a subquery with those but SQL guy I am not. Here's what I have so far:

SELECT e.*
FROM ActualData e
OUTER LEFT JOIN TempTable i
ON e.Name = i.Name WHERE i.Name IS NULL

This does give me some data, but only the ones that don't appear in ANY of the records of the ActualData table.

CodePudding user response:

You may use partitioned join with static list on status column to generate rows with missing statuses for each partition column (fk_id).

with test_tab(FK_ID, Name, Updated_Date) as (
select 1, 'PLANNED', '[Some Date]' from dual union all
select 1, 'DOING', '[Some Date]' from dual union all
select 2, 'PLANNED', '[Some Date]' from dual union all
select 2, 'DOING', '[Some Date]' from dual union all
select 2, 'DONE', '[Some Date]' from dual union all
select 3, 'PLANNED', '[Some Date]' from dual
)
select
  a.fk_id,
  b.column_value as name,
  a.updated_date
from table(sys.odcivarchar2list(
    'PLANNED',
    'DOING',
    'DONE'
  )) b
  left join test_tab a
    partition by (fk_id)
  on a.name = b.column_value
FK_ID | NAME    | UPDATED_DATE
----: | :------ | :-----------
    1 | DOING   | [Some Date] 
    1 | DONE    | null        
    1 | PLANNED | [Some Date] 
    2 | DOING   | [Some Date] 
    2 | DONE    | [Some Date] 
    2 | PLANNED | [Some Date] 
    3 | DOING   | null        
    3 | DONE    | null        
    3 | PLANNED | [Some Date]

db<>fiddle here

CodePudding user response:

One approach could be to use a cross join to get all the combinations, and then remove those that already exist:

SELECT fk_id, t.name
FROM   ActualData
CROSS JOIN temp_table t
MINUS
SELECT fk_id, name
FROM   ActualData

Of course, this query can be used to insert the "missing" rows back into ActualData:

INSERT INTO ActualData (fk_id, name)
SELECT fk_id, t.name
FROM   ActualData
CROSS JOIN temp_table t
MINUS
SELECT fk_id, name
FROM   ActualData
  • Related