Search code examples
sqlvertica

SQL Select only missing months


Notice the 2017-04-01, 2018-02-01, 2018-07-01, and 2019-01-01 months are missing in the output. I want to show only those months which are missing. Does anyone know how to go about this?

Query:

SELECT TO_DATE("Month", 'mon''yy') as dates FROM sample_sheet
group by dates
order by dates asc;

Output:

2017-01-01
2017-02-01
2017-03-01
2017-05-01
2017-06-01
2017-07-01
2017-08-01
2017-09-01
2017-10-01
2017-11-01
2017-12-01
2018-01-01
2018-03-01
2018-04-01
2018-05-01
2018-06-01
2018-08-01
2018-09-01
2018-10-01
2018-11-01
2018-12-01
2019-02-01
2019-03-01
2019-04-01

Solution

  • I don't know Vertica, so I wrote a working proof of concept in Microsoft SQL Server and tried to convert it to Vertica syntax based on the online documentation.

    It should look like this:

    with 
    months as (
       select 2017 as date_year, 1 as date_month, to_date('2017-01-01', 'YYYY-MM-DD') as first_date, to_date('2017-01-31', 'yyyy-mm-dd') as last_date
       union all
       select
          year(add_months(first_date, 1)) as date_year,
          month(add_months(first_date, 1)) as date_month, 
          add_months(first_date, 1) as first_date, 
          last_day(add_months(first_date, 1)) as last_date 
       from months
       where first_date < current_date
    ),
    sample_dates (a_date) as (
       select to_date('2017-01-15', 'YYYY-MM-DD') union all
       select to_date('2017-01-22', 'YYYY-MM-DD') union all
       select to_date('2017-02-01', 'YYYY-MM-DD') union all
       select to_date('2017-04-15', 'YYYY-MM-DD') union all
       select to_date('2017-06-15', 'YYYY-MM-DD') 
    )
    select * 
    from sample_dates right join months on sample_dates.a_date between first_date and last_date
    where sample_dates.a_date is null
    

    Months is a recursive dynamic table that holds all months since 2017-01, with first and last day of the month. sample_dates is just a list of dates to test the logic - you should replace it with your own table.

    Once you build that monthly calendar table all you need to do is check your dates against it using an outer query to see what dates are not between any of those periods between first_date and last_date columns.