Question

I have a database table that contains the following data:

ID | Date       | Bla
1  | 2013-05-01 | 1
2  | 2013-05-02 | 2
3  | 2013-05-03 | 3
4  | 2013-05-05 | 4

Note that there is a date missing: 2014-05-04. How should I alter the following query:

SELECT * 
FROM table 
where DATE >= '2013-05-01' AND DATE <= '2013-05-05'

So that I would end up with the following output:

ID   | Date       | Bla
1    | 2013-05-01 | 1
2    | 2013-05-02 | 2
3    | 2013-05-03 | 3
null | 2013-05-04 | null
4    | 2013-05-05 | 4

Is this possible?

Was it helpful?

Solution

You can join with a generate_series output:

select
    '2013-05-01'::date + g.o AS "date with offset"
from
    generate_series(0, 30) AS g(o)

Output:

"2013-05-01"
"2013-05-02"
"2013-05-03"
...
"2013-05-29"
"2013-05-30"
"2013-05-31"

Or... an easier method after defining a new stored procedure :)

CREATE OR REPLACE FUNCTION generate_series(date, date) RETURNS
SETOF date AS $$
SELECT $1 + g.s
FROM generate_series(0, ($2 - $1)) AS g(s);
$$ LANGUAGE SQL IMMUTABLE;

Just call it like this:

SELECT * FROM generate_series(start_date, end_date);

OTHER TIPS

select *
from 
    (
        select generate_series(
            '2013-05-01'::date, '2013-05-05', '1 day'
            )::date
    ) s("date")
    left join
    t using ("date")

Replace both "date" with the actual column name.

You need to outer join your table against a "list of dates":

with all_dates (some_date) as (
    select date '2013-05-01' + i 
    from generate_series(0, 10) i  -- adjust here to the range of dates you need.
) 
select t.id, 
       ad.some_date, -- you need to take the actual date from generated ones
       t.bla
from all_dates ad
  left join the_table t on ad.some_date = t.date
where ad.some_date between date '2013-05-01' and date '2013-05-05';

Btw: date is a horrible name for a column. Apart from the fact that it is a reserved word it also tells nothing about what kind of "date" that is.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top