Как перечислить записи с условными значениями и неотсутствующие записи

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

Требование: список всех сотрудников, достигших цели не менее 100% во ВСЕХ кварталах за последние два года.

"B" получил 90 % в двух разных кварталах. Сотрудник, получивший менее 100 %, НЕ ДОЛЖЕН быть указан в списке.
Обратите внимание, что вариант "A" не работал во втором квартале 2016 г.. Сотрудник, который не работал в этом квартале, НЕ ДОЛЖЕН быть указан.
"C" — единственный, кто проработал полные два года и получил 100 % в каждом квартале.

Изменить: добавлена ​​ссылка на изображение с указанием имени сотрудника, квартала, года и оценки. https://i.imgur.com/FIXR0YF.png


person Athar    schedule 18.07.2017    source источник


Ответы (1)


Логика довольно проста, это математика с четвертями, что немного больно.

За последние два года было 8 кварталов, поэтому вам просто нужно выбрать все имена сотрудников за последние два года с целью >= 100%, сгруппировать по имени сотрудника и применить предложение HAVING, чтобы ограничить вывод для этих сотрудников. с count(*) = 8.

Чтобы получить текущий год и квартал, вы можете использовать следующие выражения:

cast(extract('year' from current_date) as integer) as yr,
(cast(extract('month' from current_date) as integer)-1) / 3 + 1 as quarter;

Вычтите 2 из текущего года, чтобы найти предыдущий год и квартал. Код будет понятнее, если вы поместите эти выражения в подзапрос, потому что они понадобятся вам несколько раз для четвертной арифметики. Чтобы выполнить арифметику четвертей, вы должны извлечь целочисленное значение четверти из сохраненных вами текстовых значений.

В целом решение должно выглядеть примерно так:

select
    employee
from
    (select employee, cast(right(quarter,1) as integer) as qtr, year 
        from your_table
        where target >= 100
        ) as tgt
    cross join (
        select 
            cast(extract('year' from current_date) as integer) as yr,
            (cast(extract('month' from current_date) as integer)-1) / 3 + 1 as quarter
        ) as qtr
where
    tgt.year between qtr.yr-1 and qtr.yr
    or (tgt.year = qtr.yr - 2 and tgt.qtr > qtr.quarter)
group by
    employee
having
    count(*) = 8;

Это не проверено.

Если вы используете Postgres и ожидаете, что будете выполнять много квартальных арифметических операций, вы можете определить пользовательский тип данных, как описано в Тип данных года и квартала для PostgreSQL

person rd_nielsen    schedule 18.07.2017