Как правильно сделать join двух таблиц с одной generate_series по датам?
Закопался в необычный для себя запрос для вывода отчётов о работе системы. Вкратце, есть 2 таблицы:
table1
CREATE TABLE table1
(
id bigint,
eventtime timestamp without time zone,
error integer
waittime interval
worktime interval
)
table2
CREATE TABLE table2
(
id bigint,
eventtime timestamp without time zone,
eventtype integer
timeall interval
timeone interval
)
table1
id | eventtime | error | waittime | worktime |
---|---|---|---|---|
1 | 2023-05-29 09:11:00 | 0 | 00:00:00.000000 | 00:00:01.000000 |
2 | 2023-05-29 09:13:00 | 1 | 00:00:02.000000 | 00:00:00.000000 |
3 | 2023-05-29 09:15:00 | 0 | 00:00:00.000000 | 00:00:02.000000 |
4 | 2023-05-29 09:16:00 | 1 | 00:00:03.000000 | 00:00:00.000000 |
5 | 2023-05-29 09:21:00 | 0 | 00:00:00.000000 | 00:00:03.000000 |
6 | 2023-05-29 09:23:00 | 1 | 00:00:02.000000 | 00:00:00.000000 |
table2
id | eventtime | eventtype | timeall | timeone |
---|---|---|---|---|
1 | 2023-05-29 09:12:00 | 1 | 00:00:01.000000 | 00:00:01.000000 |
2 | 2023-05-29 09:14:00 | 2 | 00:00:02.000000 | 00:00:01.000000 |
3 | 2023-05-29 09:16:00 | 3 | 00:00:01.000000 | 00:00:02.000000 |
4 | 2023-05-29 09:17:00 | 4 | 00:00:03.000000 | 00:00:01.000000 |
5 | 2023-05-29 09:21:00 | 1 | 00:00:01.000000 | 00:00:03.000000 |
6 | 2023-05-29 09:22:00 | 3 | 00:00:02.000000 | 00:00:01.000000 |
Эти таблицы содержат отметки о разных событиях, которые произошли в определённое время, описан тип события и некое время, на него затраченное тем или иным способом.
Мне требуется составить запрос, с помощью которого я мог бы показать отчёт по этим данным за определённые промежутки времени.
Например, я хочу получить запрос для периода времени от 2023-05-29 09:00:00 до 2023-05-29 09:30:00 с разбивкой на интервалы по 10 минут. В запросе должны быть указаны эти интервалы времени, общее количество записей в соответствующем промежутке времени из первой таблицы, сколько при этом было записей с error != 0
, среднее время waittime
и среднее worktime
для каждого промежутка времени, а также из второй таблицы для каждого промежутка времени рассчитать кол-во записей с eventtype=1
, с eventtype=2
, среднее время timeall
при eventtype=1
, рассчитать кол-во записей с eventtype=3
, с eventtype=4
, среднее время timeone
при eventtype=3
.
Для этого я составляю следующий запрос:
select gen_series,
count(t1.eventtime) as eventtime1,
count( case
when t1.error!=0 then 1
end) as error1,
COALESCE(cast(avg(t1.waittime ) as varchar), '00:00:00.000000') as waittime,
COALESCE(cast(avg(t1.worktime ) as varchar), '00:00:00.000000') as worktime,
count(case
when t2.eventtype=1 then 1
end) as eventtype1,
count(case
when t2.eventtype=2 then 1
end) as eventtype2,
COALESCE(cast(avg(case
when t2.eventtype=1 then t2.timeall
end)as varchar),'00:00:00.000000') as timeall,
count(case
when t2.eventtype=3 then 1
end) as eventtype3,
count(case
when t2.eventtype=4 then 1
end) as eventtype4,
COALESCE(cast(avg(case
when t2.eventtype=3 then t2.timeone
end)as varchar),'00:00:00.000000') as timeone
from generate_series('2023-05-29 09:00:00', '2023-05-29 09:30:00', interval '10 min') as gen_series
left outer join table1 t1 on (t1.eventtime>=gen_series and t1.eventtime<=gen_series+interval '10 min')
left outer join table2 t2 on (t2.eventtime>=gen_series and t2.eventtime<=gen_series+interval '10 min')
group by gen_series
order by gen_series
Когда я делаю join
только с первой таблицей, то всё считается правильно:
gen_series | eventtime1 | error1 | waittime | worktime |
---|---|---|---|---|
2023-05-29 09:00:00 | 0 | 0 | 00:00:00.000000 | 00:00:00.000000 |
2023-05-29 09:10:00 | 4 | 2 | 00:00:02.500000 | 00:00:01.500000 |
2023-05-29 09:20:00 | 2 | 1 | 00:00:01.000000 | 00:00:01.500000 |
2023-05-29 09:30:00 | 0 | 0 | 00:00:00.000000 | 00:00:00.000000 |
Когда я делаю join
только со второй таблицей, то также всё считается правильно:
gen_series | eventtype1 | eventtype2 | timeall | eventtype3 | eventtype4 | timeone |
---|---|---|---|---|---|---|
2023-05-29 09:00:00 | 0 | 0 | 00:00:00.000000 | 0 | 0 | 00:00:00.000000 |
2023-05-29 09:10:00 | 1 | 1 | 00:00:01.000000 | 1 | 1 | 00:00:02.000000 |
2023-05-29 09:20:00 | 1 | 0 | 00:00:01.000000 | 1 | 0 | 00:00:01.000000 |
2023-05-29 09:30:00 | 0 | 0 | 00:00:00.000000 | 0 | 0 | 00:00:00.000000 |
Но как только я пытаюсь написать их вместе с двумя join
, как написано у меня в большом запросе выше, всё работает не совсем как надо.
Половина с table2
считается верно, но в половине с table1
возникает куча дубликатов на каждую запись, выведенную из table2
.
Получается что-то в таком духе:
gen_series | eventtime1 | error1 | waittime | worktime | eventtype1 | eventtype2 | timeall | eventtype3 | eventtype4 | timeone |
---|---|---|---|---|---|---|---|---|---|---|
2023-05-29 09:00:00 | 0 | 0 | 00:00:00.000000 | 00:00:00.000000 | 0 | 0 | 00:00:00.000000 | 0 | 0 | 00:00:00.000000 |
2023-05-29 09:10:00 | 16 | 8 | 00:00:02.500000 | 00:00:01.500000 | 1 | 1 | 00:00:01.000000 | 1 | 1 | 00:00:02.000000 |
2023-05-29 09:20:00 | 8 | 4 | 00:00:01.000000 | 00:00:01.500000 | 1 | 0 | 00:00:01.000000 | 1 | 0 | 00:00:01.000000 |
2023-05-29 09:30:00 | 0 | 0 | 00:00:00.000000 | 00:00:00.000000 | 0 | 0 | 00:00:00.000000 | 0 | 0 | 00:00:00.000000 |
Чувствую, что упускаю какую-то мелочь в запросе, которая на это влияет, но никак не могу понять, какую. Есть какие-нибудь идеи?
Может, есть какой-то иной способ решения или существует какая-нибудь команда типа UNION
, но которая просто ставит рядом 2 запроса :D