# function 분리
## function 분리 이유
- GET_HR_TOTAL_ANNUAL_USED_COUNT
- GET_HR_TOTAL_ANNUAL_REQ_COUNT
- 위 두 개의 펑션 때문에 속도가 느리다.
- 펑션을 해당 쿼리에서 제거하고 서비스 레이어에서 조합하고 병렬 처리를 한다.
### function이 사용된 쿼리
```xml=
SELECT @rownum:=@rownum+1 AS RNUM
, (PAGE_COUNT - PAGE_OFFSET + 1 - @rownum) AS NUM_ASC
, (PAGE_OFFSET + @rownum) AS NUM_DESC
, NULL AS MANIPULATION_TYPE
, NULL AS CHECKBOX_SELECT
, NULL AS CHECKBOX_DELETE
, T.LEAVE_ANNUAL_ID
, T.EMPLOYEE_ID
, T.COMPANY_ORIGINAL_ID
, GET_COMMON_CODE_VALUE('ORG_COMPANY_CODE', T.COMPANY_ORIGINAL_ID, IFNULL('ko', 'KO'), T.RETIRE_YMD, NULL) AS COMPANY_ORIGINAL_ID_NAME /* 법인명 */
, T.ORGANIZATION_ID
, T.ORGANIZATION_NAME
, T.DUTY_CODE
, GET_COMMON_CODE_VALUE('PHM_DUTY_CD', T.DUTY_CODE, IFNULL('ko', 'KO'), NOW(), IFNULL(127515, '')) AS DUTY_NAME
, T.EMPLOYEE_NUMBER
, T.EMPLOYEE_NAME
, CASE WHEN IFNULL(null, 'N') = 'Y' THEN DATE_FORMAT(T.HIRE_YMD, '%Y-%m-%d')
ELSE T.HIRE_YMD
END AS HIRE_YMD
, CASE WHEN IFNULL(null, 'N') = 'Y' THEN DATE_FORMAT(T.GROUP_HIRE_YMD, '%Y-%m-%d')
ELSE T.GROUP_HIRE_YMD
END AS GROUP_YMD
, CASE WHEN IFNULL(null, 'N') = 'Y' THEN DATE_FORMAT(T.RETIRE_YMD, '%Y-%m-%d')
ELSE T.RETIRE_YMD
END AS RETIRE_YMD
, T.STANDARD_YEAR
, CASE WHEN IFNULL(null, 'N') = 'Y' THEN DATE_FORMAT(T.WORK_YMD, '%Y-%m-%d')
ELSE T.WORK_YMD
END AS WORK_YMD
, CASE WHEN IFNULL(null, 'N') = 'Y' THEN DATE_FORMAT(T.START_YMD, '%Y-%m-%d')
ELSE T.START_YMD
END AS START_YMD
, CASE WHEN IFNULL(null, 'N') = 'Y' THEN DATE_FORMAT(T.END_YMD, '%Y-%m-%d')
ELSE T.END_YMD
END AS END_YMD
, T.CARRIED_FORWARD_DAYS
, CASE WHEN T.ANNUAL = 0 OR 15 > T.CREATE_DAYS_1
THEN T.CREATE_DAYS_1
ELSE 15
END AS CREATE_DAYS_1 -- 기본연차
, CASE WHEN T.ANNUAL = 0 OR 15 > T.CREATE_DAYS_1 THEN 0
ELSE T.CREATE_DAYS_1 - 15
END AS ADD_YEAR_NUM -- 가산연차
, T.CREATE_DAYS_2
, T.CREATE_START_YMD
, T.CREATE_END_YMD
, T.USED_NUM AS USE_DAYS -- 사용일수
, T.USE_CORRECTION_DAYS -- 사용조정
, T.REQ_NUM
, T.YEAR_NUM_CHANGE -- 이월 (연차보정)
, T.CREATE_DAYS_1 + T.YEAR_NUM_CHANGE + T.CARRIED_FORWARD_DAYS AS TOTAL_YEAR_NUM_1 -- 발생연차
, T.CREATE_DAYS_2 AS TOTAL_YEAR_NUM_2
, (T.CREATE_DAYS_1 + T.YEAR_NUM_CHANGE + T.CARRIED_FORWARD_DAYS) - T.USED_NUM - T.USE_CORRECTION_DAYS AS REMAINDER_DAYS_1 -- 잔여일수
, T.CREATE_DAYS_2 - T.USED_NUM - T.USE_CORRECTION_DAYS AS REMAINDER_DAYS_2
, (T.CREATE_DAYS_1 + T.YEAR_NUM_CHANGE + T.CARRIED_FORWARD_DAYS) - T.USED_NUM - T.USE_CORRECTION_DAYS - T.REQ_NUM AS POSSIBLE_DAYS_1 -- 사용가능일수
, T.CREATE_DAYS_2 - T.USED_NUM - T.USE_CORRECTION_DAYS - T.REQ_NUM AS POSSIBLE_DAYS_2
, T.HIRE_SERVICE_DAYS
, T.HIRE_SERVICE_MONTHS
, T.HIRE_SERVICE_YEARS
, CASE WHEN T.ANNUAL = 0 THEN DATE_FORMAT(T.GROUP_HIRE_YMD, '%Y-%m-%d')
ELSE STR_TO_DATE(CONCAT('2025', '0101'), '%Y%m%d')
END AS USE_BASE_START_YMD
, STR_TO_DATE(CONCAT('2025', '1231'), '%Y%m%d') AS USE_BASE_END_YMD
, T.NOTE
, T.REMAIN_NUM -- 연차정산
FROM (
SELECT @rownum:=0
, A.LEAVE_ANNUAL_ID
, A.EMPLOYEE_ID
, E.COMPANY_CODE
, H.COMPANY_ORIGINAL_ID
, H.ORGANIZATION_ID
, H.DUTY_CODE
, O.ORGANIZATION_SORT
, GET_HR_ORGANIZATION_NAME(IFNULL('10', '10'),
H.ORGANIZATION_ID, E.RETIRE_YMD, IFNULL('ko', 'KO')) AS ORGANIZATION_NAME
, E.EMPLOYEE_NUMBER
, E.EMPLOYEE_NAME
, E.HIRE_YMD
, '2025' - DATE_FORMAT(E.GROUP_HIRE_YMD, '%Y') AS ANNUAL
, E.GROUP_HIRE_YMD
, E.RETIRE_YMD
, A.STANDARD_YEAR
, A.WORK_YMD
, A.START_YMD
, A.END_YMD
, A.CARRIED_FORWARD_DAYS
, A.CREATE_DAYS_1
, A.CREATE_DAYS_2
, A.CREATE_START_YMD
, A.CREATE_END_YMD
, GET_HR_TOTAL_CHANGE_YEAR_NUM(A.EMPLOYEE_ID, A.STANDARD_YEAR) AS YEAR_NUM_CHANGE
, IFNULL(GET_HR_TOTAL_ANNUAL_USED_COUNT(A.COMPANY_ORIGINAL_ID, A.EMPLOYEE_ID, A.STANDARD_YEAR), 0) AS USED_NUM
, IFNULL(GET_HR_TOTAL_ANNUAL_REQ_COUNT(A.COMPANY_ORIGINAL_ID, A.EMPLOYEE_ID, A.STANDARD_YEAR), 0) AS REQ_NUM
, TIMESTAMPDIFF(DAY,E.GROUP_HIRE_YMD,NOW()) AS HIRE_SERVICE_DAYS
, TIMESTAMPDIFF(MONTH,E.GROUP_HIRE_YMD,NOW()) AS HIRE_SERVICE_MONTHS
, TIMESTAMPDIFF(YEAR,E.GROUP_HIRE_YMD,NOW()) AS HIRE_SERVICE_YEARS
, A.NOTE
, IFNULL(T2.REMAIN_NUM, 0) AS REMAIN_NUM
, IFNULL(0, 0) AS PAGE_OFFSET
, IFNULL(432, 0) AS PAGE_COUNT
, (
SELECT COALESCE(SUM(HLAUC.AMOUNT), 0)
FROM HTM_LEAVE_ANNUAL_USE_CORRECTION HLAUC
WHERE HLAUC.STANDARD_YEAR = A.STANDARD_YEAR
AND HLAUC.EMPLOYEE_ID = A.EMPLOYEE_ID
AND HLAUC.IS_DELETED = FALSE
) AS USE_CORRECTION_DAYS
FROM HTM_LEAVE_ANNUAL A
INNER JOIN PER_EMPLOYEES E
ON A.EMPLOYEE_ID = E.EMPLOYEE_ID
INNER JOIN ASS_ASSIGNMENT_HISTORYS H
ON A.EMPLOYEE_ID = H.EMPLOYEE_ID
AND CURRENT_DATE() BETWEEN H.START_YMD AND H.END_YMD
AND H.ASSIGNMENT_DIVISION_CODE = '1'
AND H.LAST_YN = 'Y'
LEFT OUTER JOIN ORG_ORGANIZATION_HISTORYS O
ON H.ORGANIZATION_ID = O.ORGANIZATION_ID
AND A.WORK_YMD BETWEEN O.START_YMD AND O.END_YMD
LEFT JOIN HTM_LEAVE_ANNUAL_ADJUSTMENT HLAA
ON HLAA.EMPLOYEE_ID = A.EMPLOYEE_ID
AND HLAA.STANDARD_YEAR = A.STANDARD_YEAR
LEFT JOIN (SELECT HLAA.COMPANY_ORIGINAL_ID, HLAA.EMPLOYEE_ID, SUM(HLAA.YEAR_NUM) - IFNULL(SUM(HLAA.USED_NUM), 0) - IFNULL((SELECT sum(HLAU.BEFORE_NUM)
FROM HTM_LEAVE_ANNUAL_USE HLAU
WHERE HLAU.COMPANY_ORIGINAL_ID = HLAA.COMPANY_ORIGINAL_ID
AND HLAU.EMPLOYEE_ID = HLAA.EMPLOYEE_ID
GROUP BY HLAU.COMPANY_ORIGINAL_ID, HLAU.EMPLOYEE_ID),
0) AS REMAIN_NUM
FROM HTM_LEAVE_ANNUAL_ADJUSTMENT HLAA
GROUP BY HLAA.COMPANY_ORIGINAL_ID, HLAA.EMPLOYEE_ID) T2
ON T2.EMPLOYEE_ID = HLAA.EMPLOYEE_ID -- 연차정산
WHERE A.COMPANY_ORIGINAL_ID = '127515'
AND A.STANDARD_YEAR = '2025'
) T
ORDER BY T.ORGANIZATION_SORT, T.EMPLOYEE_NAME, T.START_YMD
---
```
## function: GET_HR_TOTAL_ANNUAL_USED_COUNT
```xml=
create
definer = aipers_app@`10.198.0.0/255.255.0.0` function GET_HR_TOTAL_ANNUAL_COUNT(PARAM_COMPANY_ORIGINAL_ID int,
PARAM_EMPLOYEE_ID int,
PARAM_EFFECTIVE_YEAR varchar(4),
PARAM_DRAFT_ID int,
ELA_STAT_CD_LOOKUP_CODE varchar(4)) returns decimal(7, 3)
comment '결재상태 룩업코드 및 연도 기준 연차휴가 사용일수'
BEGIN
DECLARE RETURN_VALUE DECIMAL(7, 3);
SELECT IFNULL(SUM(TT.FIRST_USED_NUM) + SUM(TT.USED_NUM) + SUM(TT.LAST_USED_NUM) + SUM(TT.LAST_DAY_USED_NUM) -
SUM(IFNULL(TT.RETIRE_USED_NUM, 0)), 0)
INTO RETURN_VALUE
FROM (SELECT CASE
-- 전년도에 시작하고 해당연도에 끝나는 연차중 올해만 사용된 갯수 계산
WHEN T.START_YMD < CONCAT(PARAM_EFFECTIVE_YEAR, '0101')
AND T.END_YMD >= CONCAT(PARAM_EFFECTIVE_YEAR, '0101')
THEN
CASE GET_COMMON_CODE_LOOKUPCODE('DTM_HOLIDAY_APPLY_TYPE', B.HOLIDAY_APPLY_TYPE, 'ko', now(),
null)
WHEN '1' THEN
IFNULL((SELECT SUM(MINUS_DD)
FROM HTM_CALENDAR C
WHERE C.COMPANY_ORIGINAL_ID = T.COMPANY_ORIGINAL_ID
AND C.SOLAR_YMD BETWEEN CONCAT(PARAM_EFFECTIVE_YEAR, '0101') AND T.END_YMD
AND C.MINUS_DD = 1), 0)
ELSE
IFNULL((SELECT COUNT(MINUS_DD)
FROM HTM_CALENDAR C
WHERE C.COMPANY_ORIGINAL_ID = T.COMPANY_ORIGINAL_ID
AND C.SOLAR_YMD BETWEEN CONCAT(PARAM_EFFECTIVE_YEAR, '0101') AND T.END_YMD),
0)
END -
CASE
WHEN T.TYPE_CODE =
GET_COMMON_CODE_ID('DTM_TYPE_CD', 103, 'ko', NOW(), NULL)
THEN 0.5
ELSE 0
END
ELSE 0
END AS FIRST_USED_NUM
-- 작년도와 내년도에 사용되는 연차는 0으로 처리
-- 하루 연차면 1 반차면 0.5
-- 여럿연차면 영업일 계산
, CASE
WHEN T.START_YMD < CONCAT(PARAM_EFFECTIVE_YEAR, '0101') THEN 0
WHEN T.END_YMD >= CONCAT(PARAM_EFFECTIVE_YEAR, '1231') THEN 0
WHEN T.START_YMD = T.END_YMD
THEN
CASE
WHEN T.TYPE_CODE IN
(GET_COMMON_CODE_ID('DTM_TYPE_CD', 102, 'ko', NOW(), NULL),
GET_COMMON_CODE_ID('DTM_TYPE_CD', 103, 'ko', NOW(), NULL))
THEN 0.5
WHEN GET_COMMON_CODE_ID('DTM_REQ_UNIT', 'T', 'ko', NOW(),
NULL) = B.REQUEST_UNIT_ID
THEN T.TOT_USE_NUM / 480
ELSE T.TOT_USE_NUM
END
ELSE
CASE GET_COMMON_CODE_LOOKUPCODE('DTM_HOLIDAY_APPLY_TYPE', B.HOLIDAY_APPLY_TYPE, 'ko', now(),
null)
WHEN '1' THEN
IFNULL((SELECT SUM(MINUS_DD)
FROM HTM_CALENDAR C
WHERE C.COMPANY_ORIGINAL_ID = T.COMPANY_ORIGINAL_ID
AND C.SOLAR_YMD BETWEEN T.START_YMD AND T.END_YMD
AND C.MINUS_DD = 1), 0)
ELSE
IFNULL((SELECT COUNT(MINUS_DD)
FROM HTM_CALENDAR C
WHERE C.COMPANY_ORIGINAL_ID = T.COMPANY_ORIGINAL_ID
AND C.SOLAR_YMD BETWEEN T.START_YMD AND T.END_YMD), 0)
END -
CASE
WHEN T.TYPE_CODE IN (
GET_COMMON_CODE_ID('DTM_TYPE_CD', 102, 'ko', NOW(), NULL),
GET_COMMON_CODE_ID('DTM_TYPE_CD', 103, 'ko', NOW(), NULL))
THEN 0.5
WHEN T.TYPE_CODE = GET_COMMON_CODE_ID('DTM_TYPE_CD', 104, 'ko', NOW(), NULL)
THEN 0.75
ELSE 0
END
END AS USED_NUM
-- 해당연도에 시작하고 내년도에 끝나는 연차중 올해만 사용된 갯수 계산
, CASE
WHEN T.END_YMD >= CONCAT(PARAM_EFFECTIVE_YEAR, '1231')
AND T.START_YMD < CONCAT(PARAM_EFFECTIVE_YEAR, '1231')
THEN
CASE GET_COMMON_CODE_LOOKUPCODE('DTM_HOLIDAY_APPLY_TYPE', B.HOLIDAY_APPLY_TYPE, 'ko', now(),
null)
WHEN '1' THEN
IFNULL((SELECT SUM(MINUS_DD)
FROM HTM_CALENDAR C
WHERE C.COMPANY_ORIGINAL_ID = T.COMPANY_ORIGINAL_ID
AND C.SOLAR_YMD BETWEEN T.START_YMD AND CONCAT(PARAM_EFFECTIVE_YEAR, '1231')
AND C.MINUS_DD = 1), 0)
ELSE
IFNULL((SELECT COUNT(MINUS_DD)
FROM HTM_CALENDAR C
WHERE C.COMPANY_ORIGINAL_ID = T.COMPANY_ORIGINAL_ID
AND C.SOLAR_YMD BETWEEN T.START_YMD AND CONCAT(PARAM_EFFECTIVE_YEAR, '1231')),
0)
END -
CASE
WHEN T.TYPE_CODE =
GET_COMMON_CODE_ID('DTM_TYPE_CD', 102, 'ko', NOW(), NULL)
THEN 0.5
ELSE 0
END
ELSE 0
END AS LAST_USED_NUM
-- 12워 31일 휴가 하루 계산
, CASE
WHEN T.START_YMD = CONCAT(PARAM_EFFECTIVE_YEAR, '1231')
THEN
CASE GET_COMMON_CODE_LOOKUPCODE('DTM_HOLIDAY_APPLY_TYPE', B.HOLIDAY_APPLY_TYPE, 'ko', now(),
null)
WHEN '1' THEN
IFNULL((SELECT SUM(MINUS_DD)
FROM HTM_CALENDAR C
WHERE C.COMPANY_ORIGINAL_ID = T.COMPANY_ORIGINAL_ID
AND C.SOLAR_YMD BETWEEN T.START_YMD AND CONCAT(PARAM_EFFECTIVE_YEAR, '1231')
AND C.MINUS_DD = 1), 0)
ELSE
IFNULL((SELECT COUNT(MINUS_DD)
FROM HTM_CALENDAR C
WHERE C.COMPANY_ORIGINAL_ID = T.COMPANY_ORIGINAL_ID
AND C.SOLAR_YMD BETWEEN T.START_YMD AND CONCAT(PARAM_EFFECTIVE_YEAR, '1231')),
0)
END -
CASE
WHEN T.TYPE_CODE IN
(GET_COMMON_CODE_ID('DTM_TYPE_CD', 102, 'ko', NOW(), NULL),
GET_COMMON_CODE_ID('DTM_TYPE_CD', 103, 'ko', NOW(), NULL))
THEN 0.5
WHEN T.TYPE_CODE = GET_COMMON_CODE_ID('DTM_TYPE_CD', 104, 'ko', NOW(), NULL)
THEN 0.75
ELSE 0
END
ELSE 0
END AS LAST_DAY_USED_NUM
, CASE
WHEN R.RETIRE_YMD IS NOT NULL THEN -- 25.01.15 퇴직일 후의 연차사용일수 계산(사용일수에서 차감목적)
CASE GET_COMMON_CODE_LOOKUPCODE('DTM_HOLIDAY_APPLY_TYPE', B.HOLIDAY_APPLY_TYPE, 'ko', now(),
null)
WHEN '1' THEN -- 25.01.15 근무일수 기준 계산
IFNULL((SELECT SUM(MINUS_DD)
FROM HTM_CALENDAR C
WHERE C.COMPANY_ORIGINAL_ID = T.COMPANY_ORIGINAL_ID
AND C.SOLAR_YMD BETWEEN
GREATEST(
ADDDATE(R.RETIRE_YMD, INTERVAL 1 DAY), -- 25.01.15 퇴직일은 근무일로 처리, 퇴직일 다음날 부터 계산 적용
GREATEST( -- 25.01.15 조회 년도 내의 연차만 계산하기 위한 목적(조회년도 1월 1일부터 범위에 포함)
T.START_YMD,
CONCAT(PARAM_EFFECTIVE_YEAR, '0101')
)
)
AND LEAST( -- 25.01.15 조회 년도 내의 연차만 계산하기 위한 목적(조회년도 12월 31일 까지만 범위에 포함)
T.END_YMD,
CONCAT(PARAM_EFFECTIVE_YEAR, '1231')
)
AND C.MINUS_DD = 1), 0)
ELSE -- 25.01.15 달력일수 기준 계산
IFNULL((SELECT COUNT(MINUS_DD)
FROM HTM_CALENDAR C
WHERE C.COMPANY_ORIGINAL_ID = T.COMPANY_ORIGINAL_ID
AND C.SOLAR_YMD BETWEEN
GREATEST(
ADDDATE(R.RETIRE_YMD, INTERVAL 1 DAY), -- 25.01.15 퇴직일은 근무일로 처리, 퇴직일 다음날 부터 계산 적용
GREATEST( -- 25.01.15 조회 년도 내의 연차만 계산하기 위한 목적(조회년도 1월 1일부터 범위에 포함)
T.START_YMD,
CONCAT(PARAM_EFFECTIVE_YEAR, '0101')
)
)
AND LEAST( -- 25.01.15 조회 년도 내의 연차만 계산하기 위한 목적(조회년도 12월 31일 까지만 범위에 포함)
T.END_YMD,
CONCAT(PARAM_EFFECTIVE_YEAR, '1231')
)), 0)
END * -- 25.01.15 곱하기: 연차 종류에 따른 사용일수 보정 복적
CASE
WHEN T.TYPE_CODE IN (
GET_COMMON_CODE_ID('DTM_TYPE_CD', 102, 'ko', NOW(), NULL), -- 25.01.15 오전반차
GET_COMMON_CODE_ID('DTM_TYPE_CD', 103, 'ko', NOW(), NULL)) -- 25.01.15 오후반차
THEN 0.5 -- 25.01.15 반차
WHEN T.TYPE_CODE =
GET_COMMON_CODE_ID('DTM_TYPE_CD', 104, 'ko', NOW(), NULL) -- 25.01.15 반반차
THEN 0.25 -- 25.01.15 반반차
ELSE 1 -- 25.01.15 연차
END
ELSE 0
END AS RETIRE_USED_NUM
FROM HTM_HOLIDAY_APPLICATION T
INNER JOIN HTM_DAILY_BASE B
ON T.COMPANY_ORIGINAL_ID = B.COMPANY_ORIGINAL_ID
AND T.TYPE_CODE = B.TYPE_CODE
AND B.END_YMD >= T.START_YMD
AND B.START_YMD <= T.START_YMD
LEFT JOIN (SELECT EMPLOYEE_ID, RETIRE_YMD
FROM PER_EMPLOYEES
WHERE RETIRE_YMD is not null
UNION
SELECT EMPLOYEE_ID, RETIRE_YMD
FROM PER_EMPLOYEE_RETIREMENTS
WHERE RETIRE_YMD <= CURRENT_DATE) R
ON T.EMPLOYEE_ID = R.EMPLOYEE_ID
AND
T.END_YMD > IFNULL(R.RETIRE_YMD, '19001231') -- 25.01.15 퇴직일은 근무일로 처리, 퇴직일 다음날부터 조인 처리
WHERE T.COMPANY_ORIGINAL_ID = PARAM_COMPANY_ORIGINAL_ID
AND T.EMPLOYEE_ID = PARAM_EMPLOYEE_ID
AND T.WORK_CODE IN (GET_COMMON_CODE_ID('DTM_WORK_CD', 100, 'ko', now(), null))
AND T.REQUEST_STATUS_CODE = GET_COMMON_CODE_ID('ELA_STAT_CD', ELA_STAT_CD_LOOKUP_CODE, 'ko', now(), null)
AND (T.DRAFT_ID != PARAM_DRAFT_ID OR T.DRAFT_ID IS NULL)) TT;
RETURN (RETURN_VALUE);
END;
```