Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Postgresql Select from date range between array of dates

If this query returns the dates that exists in the range requested.

select created_at from user where created_at between '2015-01-06 00:00:00.000000' and '2015-03-06 00:00:00.000000'

Is there a way to obtain such result but with multiple dates contained with an array of dates.

Just for an example of what im trying to say. i have this array of date, always there's gonna be a first and last date.

Array['2015-01-06 00:00:00.000000','2015-02-10 15:17:18.895000' <- First range
      '2017-10-05 14:41:04.191000','2017-10-11 14:49:36.454000' <- Second range

so is there a way to put a script that goes something like this?

select created_at from win_users 
where (created_at between [First Date] and [Second Date])
or (created_at between [Third Date] and [Fourth Date])

but without using a loop to concat the where statement?

like image 246
Luis Cardoza Bird Avatar asked Aug 24 '26 16:08

Luis Cardoza Bird


1 Answers

An array of dates is very uncomfortable in this case. Use arrays of daterange and the containtment operator <@, e.g.:

with my_table(id, created_at) as (
values 
    (1, '2015-01-10'::timestamp),
    (2, '2016-05-10'),
    (3, '2017-10-10')
)

select *
from my_table
where created_at::date <@ any(array[
    daterange('2015-01-06','2015-02-10'), 
    daterange('2017-10-05','2017-10-11')])

 id |     created_at      
----+---------------------
  1 | 2015-01-10 00:00:00
  3 | 2017-10-10 00:00:00
(2 rows)

If you absolutely want to use an array of dates (honestly I do not think so), use this function to convert it to daterange array:

create or replace function date_pairs_to_ranges(date[])
returns daterange[] language sql as $$
    select array_agg(daterange(d1, d2))
    from unnest($1) with ordinality as u1(d1, o1)
    join unnest($1) with ordinality as u2(d2, o2)
    on o1/ 2* 2 < o1 and o2 = o1+ 1
$$;

with my_table(id, created_at) as (
values 
    (1, '2015-01-10'::timestamp),
    (2, '2016-05-10'),
    (3, '2017-10-10')
)

select *
from my_table
where created_at::date <@ any(
    date_pairs_to_ranges(array[
        '2015-01-06','2015-02-10',
        '2017-10-05','2017-10-11']::date[]))
like image 145
klin Avatar answered Aug 26 '26 06:08

klin



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!