У меня есть требование получить список сотрудников, а для каждого сотрудника список месяцев, в течение которых они активно получали льготы в данном году. Существует таблица с данными о работе и таблица с информацией о преимуществах. Существует также таблица дат доставки, в которой перечислены все даты с 2007 по 2018 год, и для каждой даты указан день месяца, месяц года и календарный год.
То, как я написал запрос сейчас, состоит в том, чтобы сказать: найти все даты в таблице дат, которые 1) между 01/01 и 12/31 года подсказки (или текущей датой, в зависимости от того, что старше), 2) во время время, когда работник был активен в таблице льгот. На каждую дату мне также нужен deptid из таблицы вакансий и план льгот из таблицы льгот на эту дату. Затем я делаю отдельные, показывая только месяц года и календарный год для каждого сотрудника.
Это работает, но проблема возникает, когда я пытаюсь сделать это для отделов, в которых работает много людей. Я полагаю, что для запуска требуется очень много времени, потому что он извлекает до 365 строк для каждого отдельного сотрудника, а затем показывает только 12 из них, поскольку он извлекает только отдельные месяцы. Я чувствую, что есть лучший способ сделать это, я просто не могу придумать, что это такое.
Вот несколько упрощенных примеров таблиц, с которыми я работаю:
Таблица дат
THE_DATE MONTHOFYEAR CALENDAR_YEAR
01-OCT-15 10 2015
02-OCT-15 10 2015
03-OCT-15 10 2015
...
Таблица вакансий
(А=активно; я=неактивно)
EMPLID EFFDT DEPTID HR_STATUS
00123 01-FEB-15 900 A
00123 30-JUN-15 900 I
00123 01-AUG-15 901 A
Таблица преимуществ
EMPLID EFFDT BENEFIT_PLAN STATUS
00123 01-MAR-15 PPO A
00123 31-JUL-15 I
00123 01-SEP-15 HMO A
Желаемый результат
EMPLID CALENDAR_YEAR MONTHOFYEAR DEPTID BENEFIT_PLAN
00123 2015 3 900 PPO
00123 2015 4 900 PPO
00123 2015 5 900 PPO
00123 2015 6 900 PPO
00123 2015 7 900 PPO
00123 2015 9 901 HMO
00123 2015 10 901 HMO
00123 2015 11 901 HMO
^ (shows November row even though employee was only covered for part of this month)
Пример SQL для получения результатов выше
SELECT DISTINCT J.EMPLID, D.CALENDAR_YEAR, D.MONTHOFYEAR, J.DEPTID, B.BENEFIT_PLAN
FROM DATES D,
JOBS J
JOIN
BENEFITS B
ON J.EMPLID = B.EMPLID
WHERE D.THE_DATE <= SYSDATE
AND D.THE_DATE BETWEEN
TO_DATE(:YEAR_PROMPT || '01-01', 'YYYY-MM-DD')
AND
TO_DATE(:YEAR_PROMPT || '12-31', 'YYYY-MM-DD')
AND B.STATUS = 'A'
AND D.THE_DATE BETWEEN
B.EFFDT
AND
NVL(SELECT MIN(B_ED.EFFDT)
FROM BENEFITS B_ED
WHERE B_ED.EMPLID = B.EMPLID
AND B_ED.EFFDT > B.EFFDT
, SYSDATE)
AND J.EFFDT = (SELECT MAX(J_ED.EFFDT)
FROM JOBS J_ED
WHERE J_ED.EMPLID = J.EMPLID
AND J_ED.EFFDT <= D.THE_DATE)
Вместо того, чтобы говорить «получить каждую дату и проверить, соответствует ли она критериям», могу ли я как-то изменить логику, чтобы получить те же результаты, не перебирая столько строк?
cross join
работаете сdates
иjobs
таблицами. - person Vamsi Prabhala   schedule 05.11.2015