Home > Enterprise >  SQL to identify missing dates in column
SQL to identify missing dates in column

Time:09-06

Is there a way to generate list of missing dates in table in Oracle?

Input

name,my_date
A,04-JAN-2000
A,05-JAN-2000
A,08-JAN-2000
A,08-JAN-2000  -- duplicates possible
A,10-JAN-2000
B,09-FEB-2001
B,10-FEB-2001
B,05-FEB-2001

Result

A,06-JAN-2000
A,07-JAN-2000
A,09-JAN-2000
B,06-FEB-2001
B,07-FEB-2001
B,08-FEB-2001

After suggestion from @diiN__________ to see Oracle: select missing dates, I managed to get it working for a specific name as follows:

WITH all_dates_wo_boundary_values as
(SELECT oldest   level my_date
    FROM (SELECT MIN(my_date) oldest
                ,MAX(my_date) recent
             FROM mytable my
             WHERE my.name = 'A'
         )
 connect by level <= recent - oldest - 1
)
 SELECT my_date
FROM all_dates_wo_boundary_values
MINUS
SELECT my_date
FROM mytable my
WHERE my.name = 'A'

How could it be done for multiple names at once?

CodePudding user response:

For multiple names, you can use the LEAD analytic function to find the next date and then CROSS JOIN LATERAL (available from Oracle 12) a row-generator to generate the missing values:

SELECT t.name,
       m.missing
FROM   (
         SELECT name,
                dt,
                LEAD(dt) OVER (PARTITION BY name ORDER BY dt) AS next_dt
         FROM   table_name
       ) t
       CROSS JOIN LATERAL (
         SELECT dt   LEVEL AS missing
         FROM   DUAL
         WHERE  dt   1 < next_dt
         CONNECT BY dt   LEVEL < next_dt
       ) m

Which, for the sample data:

CREATE TABLE table_name (Name,dt) AS
  SELECT 'A', DATE '2000-01-04' FROM DUAL UNION ALL
  SELECT 'A', DATE '2000-01-05' FROM DUAL UNION ALL
  SELECT 'A', DATE '2000-01-08' FROM DUAL UNION ALL
  SELECT 'A', DATE '2000-01-08' FROM DUAL UNION ALL
  SELECT 'A', DATE '2000-01-10' FROM DUAL UNION ALL
  SELECT 'B', DATE '2001-02-05' FROM DUAL UNION ALL
  SELECT 'B', DATE '2001-02-09' FROM DUAL UNION ALL
  SELECT 'B', DATE '2001-02-10' FROM DUAL;

Outputs:

NAME MISSING
A 06-JAN-00
A 07-JAN-00
A 09-JAN-00
B 06-FEB-01
B 07-FEB-01
B 08-FEB-01

db<>fiddle here

  • Related