Это без рекурсии.
Идея состоит в том, чтобы получить список всех ваших людей с их first_time_em
датой. Использование предложений left join
и filter
вернет всех людей, независимо от того, достигли ли они когда-либо уровня EM.
Присоедините этот результат обратно к самому себе, соединяя каждую запись с ее родительской записью. Опять же, это left join
, поскольку человек на вершине иерархии не должен иметь родителя.
Оператор case
может быть просто boolean
сравнением с coalesce
, поскольку все, что нам нужно, это true
/ false
. Возможные условия:
- Детский
first_time_em
перед родительским first_time_em
, что дает true
- У ребенка
first_time_em
, а у босса нет (null
), которое coalesce()
превращается в 9999-12-31
, что дает true
- У ребенка нет
first_time_em
(null
), дает false
по else
- Детский
first_time_em
находится после родительского first_time_em
, дает false
по 'else` - Ни у ребенка, ни у родителя нет
first_time_em
, дает false
по else
with person_achievement as (
select p.person_id, p.parent_id,
MIN(ra."EffectiveDate")
filter (when ra."NewRank" in
('Executive Manager', 'Associate Director', 'Director',
'Senior Director', 'Executive Director', 'Managing Director')
) as first_time_em
from person p
left join rankachievement ra
on ra.person_id = p.person_id
)
select pc.*,
case
when pc.first_time_em < coalesce(pp.first_time_em, '9999-12-31') then true
else false
end as made_em_before_boss
from person_achievement pc
left join person_achievement pp
on pp.person_id = pc.parent_id
;