Как выбрать количество сущностей, где дата временного ряда находится между датой начала и датой окончания этой сущности

#sql #postgresql

Вопрос:

Я бы хотел выбрать дневную серию, примерно такую:

 SELECT generate_series(
   timestamp without time zone '2016-10-16',
   timestamp without time zone '2016-10-17',
   '1 day')
 

Далее я получил сущности, у которых всегда есть дата начала и дата окончания.
С помощью приведенного выше запроса я хотел бы выбрать количество (количество) объектов, у которых этот день в серии находится внутри обеих дат.

Вывод будет (вроде) таким: выберите вывод

Любая помощь будет признательна!

изменить: Вот пример таблицы:

 table occurrences (
    datestart DATE
    dateend DATE
)
 

Комментарии:

1. Пожалуйста, предоставьте примерные данные и желаемые результаты.

2. Пожалуйста, поделитесь структурами таблиц сущностей.

Ответ №1:

Операторы схемы и вставки:

  create table entities (id int, startdate date,enddate date);
 insert into entities values(1, '2016-10-10','2016-10-18');
 insert into entities values(1, '2016-10-10','2016-10-16');
 insert into entities values(1, '2016-10-15','2016-10-16');
 insert into entities values(1, '2016-10-17','2016-10-18');
 

Запрос:

  with dateseries as
 (
 SELECT generate_series(
    timestamp without time zone '2016-10-16',
    timestamp without time zone '2016-10-20',
    '1 day')
 
 )
 select generate_series,
 (select count(*) from entities e where d.generate_series between e.startdate and e.enddate)  entities_count
 from dateseries d 
 

Выход:

generate_series количество сущностей
2016-10-16 00:00:00 3
2016-10-17 00:00:00 2
2016-10-18 00:00:00 2
2016-10-19 00:00:00 0
2016-10-20 00:00:00 0

db<поиграй здесь

Комментарии:

1. @Дон, добро пожаловать. Приятно знать, что это помогло. Наилучшие пожелания.

Ответ №2:

Если я правильно понимаю, вы можете сделать что-то вроде этого:

 SELECT gs.dte, COUNT(e.entity_id)
FROM generate_series('2016-10-16'::date, '2016-10-17'::date, '1 day') gs(dte) LEFT JOIN
     entities e
     ON e.startdate < gs.dte   interval '1 day' AND
        e.enddate >= gs.dte
GROUP BY gs.dte;
 

Даты кажутся достаточными для логики, которую вы хотите реализовать, но вы, конечно, можете вместо этого использовать метки времени.