Как сократить время загрузки с несколькими подзапросами и объединениями? - PullRequest
0 голосов
/ 14 января 2019

У меня есть запрос, чтобы найти, какой v_address принадлежал какой v_group, и когда была дата создания v_address. Однако каждая v_group иногда была активной и неактивной, и у нее были даты. Итак, я написал запрос, чтобы найти период этих изменений.

Моя проблема в том, что мой запрос выполнялся слишком долго, потому что он имеет несколько подзапросов и объединений.

У кого-нибудь есть идея сократить загрузку данных?
Я прикрепил свой запрос ниже identifier = 81 для меньшего тестирования. Для окончательного результата мне нужно будет получить данные для более чем 100 000 идентификаторов.

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

with v_address as (
    select id, v_group_id, created_at
    from prod.venue_address --different schema and table. v_address.v_group_id can have multiple v_address.id
    group by 1,2,3
    order by 3 asc
    ),
v_group as (
    select identifier, final_status, created_at
    from dwh.venue_address_archive
    where identifier = 81
    group by 1,2,3
    order by 3 asc
    ),
filtering as (
    select identifier, created_at,
    case when sum(case when final_state = 'active' then 1 else 0 end) > 0 then 'active' else 'inactive' end as filtered_status --This filters either of active or inactive
    from v_group
    group by 1,2
    order by 2 asc
    ),
prev as (
    select identifier, created_at, filtered_status,
    lag(case when filtered_status = 'active' then 'active' else 'inactive' end) over (partition by identifier order by created_at) = filtered_status as is_prev_status
    from filtering
    group by 1,2,3
    ),
periods as (
    select identifier, filtered_status, created_at, is_prev_status,
    sum(case when is_prev_status = true then 0 else 1 end) over (order by identifier, created_at) as period
    from prev
    group by 1,2,3,4
    ),
islands_gaps_start as (
    select identifier, period, min(created_at) as start_at
    from periods
    group by 2,1
    ),
islands_gaps as (
    select identifier, period, start_at,
    lead(start_at) over (partition by identifier order by period) as end_at
    from islands_gaps_start
    )
select vg.identifier as "vg_id", p.created_at as "vg_created_at", p.filtered_status as "status", p.is_prev_status, p.period, va.id as "va_id", g.start_at, g.end_at
from v_address va
left join v_group vg
on va.venue_id = vg.identifier
inner join filtering f
on vg.identifier = f.identifier
inner join prev pr
on pr.filtered_status = f.filtered_status
inner join periods p
on p.filtered_status = pr.filtered_status
inner join islands_gaps_start gs
on p.period = gs.period
inner join islands_gaps g
on gs.start_at = g.start_at
group by 6,1,2,3,4,5,7,8
order by 2 asc

У меня уже есть вывод с примером identifier = 81, но мне нужно выполнить этот запрос для более чем 100 000 идентификаторов, поэтому я ищу любой совет, который может сократить мой запрос.

...