I have created a query to get differnt time types and hours
SELECT calc_time.hours measure,
calc_time.payroll_time_type elements,
calc_time.person_id,
calc_time.start_time
FROM hwm_tm_rep_work_hours_sum_v calc_time,
per_all_people_f papf
WHERE grp_type_id = 200
AND payroll_time_type IN ( 'Afternoon shift',
'TL',
'Evening shift',
'Regular Pay ',
'OT' )
AND (
To_date(To_char(calc_time.start_time, 'YYYY-MM-DD') , 'YYYY-MM-DD') BETWEEN To_date(To_char(:From_Date, 'YYYY-MM-DD'), 'YYYY-MM-DD')
AND To_date( To_char(:To_Date, 'YYYY-MM-DD'), 'YYYY-MM-DD' ) )
and papf.person_id = calc_time.person_id
I get the output like -
Start_time person_id elements measure
01-Jan-2021 198 Regular Pay 10
01-Jan-2021 198 OT 2
01-jAN-2021 198 Afternoon shift 2
16-JAN-2021 198 Regular Pay 10
17-JAN-2021 198 OT 3
20-JAN-2021 198 EVENING SHIFT 8
08-JAN-2021 11 Regular Pay 8
09-JAN-2021 11 OT 1
08-JAN-2021 11 tl 2
10-JAN-2021 12 Evening shift 9
11-JAN-2021 12 Evening shift 9
I want this output to be dispplayed as follows WITHIN TWO DATES THAT I PASS AS PARAMETER - LIKE PARAMETER TO AND FROM DATE 01-JAN-2021 AND 31-JAN-2021
person_id Regular_pay OT OTHER_MEASURE OTHER_CODE
198 20 5 2 Afternoon shift
198 20 5 8 EVENING SHIFT
11 8 1 2 TL
12 18 Evening shift
So sum of Regular pay and OT IN seperate columns and all others in other_measure and other_code
How can i tweak the main query to achieve this ?
CodePudding user response:
You could try something like this - In your question, unfortunately, it is not clear in which table which columns/values are available.
SELECT
calc_time.person_id,
(select sum(calc_time.start_time) FROM hwm_tm_rep_work_hours_sum_v calc_time where papf.person_id = calc_time.person_id and calc_time.payroll_time_type = 'Regular Pay') as Regular_Pay,
...
FROM hwm_tm_rep_work_hours_sum_v calc_time,
per_all_people_f papf
WHERE grp_type_id = 200
AND payroll_time_type IN ( 'Afternoon shift',
'TL',
'Evening shift',
'Regular Pay ',
'OT' )
AND (
To_date(To_char(calc_time.start_time, 'YYYY-MM-DD') , 'YYYY-MM-DD') BETWEEN To_date(To_char(:From_Date, 'YYYY-MM-DD'), 'YYYY-MM-DD')
AND To_date( To_char(:To_Date, 'YYYY-MM-DD'), 'YYYY-MM-DD' ) )
and papf.person_id = calc_time.person_id
-- use a group by
GROUP BY
calc_time.person_id
CodePudding user response:
You can use:
SELECT *
FROM (
SELECT c.person_id,
SUM(CASE c.payroll_time_type WHEN 'Regular Pay' THEN SUM(c.hours) END)
OVER (PARTITION BY c.person_id) AS regular_pay,
SUM(CASE c.payroll_time_type WHEN 'OT' THEN SUM(c.hours) END)
OVER (PARTITION BY c.person_id) AS OT,
SUM(c.hours) AS other_measure,
c.payroll_time_type AS Other_code
FROM hwm_tm_rep_work_hours_sum_v c
INNER JOIN per_all_people_f p
ON (p.person_id = c.person_id)
WHERE grp_type_id = 200
AND payroll_time_type IN (
'Afternoon shift',
'TL',
'Evening shift',
'Regular Pay',
'OT'
)
AND c.start_time >= TRUNC(:from_date)
AND c.start_time < TRUNC(:to_date) INTERVAL '1' DAY
GROUP BY
c.person_id,
c.payroll_time_type
)
WHERE other_code NOT IN ('Regular Pay', 'OT');
Which, for the sample data:
CREATE TABLE hwm_tm_rep_work_hours_sum_v (start_time, person_id, payroll_time_type, hours) AS
SELECT DATE '2021-01-01', 198, 'Regular Pay', 10 FROM DUAL UNION ALL
SELECT DATE '2021-01-01', 198, 'OT', 2 FROM DUAL UNION ALL
SELECT DATE '2021-01-01', 198, 'Afternoon shift', 2 FROM DUAL UNION ALL
SELECT DATE '2021-01-16', 198, 'Regular Pay', 10 FROM DUAL UNION ALL
SELECT DATE '2021-01-17', 198, 'OT', 3 FROM DUAL UNION ALL
SELECT DATE '2021-01-20', 198, 'Evening shift', 8 FROM DUAL UNION ALL
SELECT DATE '2021-01-08', 11, 'Regular Pay', 8 FROM DUAL UNION ALL
SELECT DATE '2021-01-09', 11, 'OT', 1 FROM DUAL UNION ALL
SELECT DATE '2021-01-08', 11, 'TL', 2 FROM DUAL UNION ALL
SELECT DATE '2021-01-10', 12, 'Evening shift', 9 FROM DUAL UNION ALL
SELECT DATE '2021-01-11', 12, 'Evening shift', 9 FROM DUAL;
CREATE TABLE per_all_people_f (person_id, grp_type_id) AS
SELECT 198, 200 FROM DUAL UNION ALL
SELECT 11, 200 FROM DUAL UNION ALL
SELECT 12, 200 FROM DUAL;
Outputs:
PERSON_ID REGULAR_PAY OT OTHER_MEASURE OTHER_CODE 11 8 1 2 TL 12 18 Evening shift 198 20 5 2 Afternoon shift 198 20 5 8 Evening shift
db<>fiddle here
CodePudding user response:
You may use aggregation and then apply model
clause to calculate the required columns. Below is the code with comments, assuming you can manage filter by dates.
select * from t
PERSON_ID | ELEMENTS | MEASURE --------: | :-------------- | ------: 198 | Regular Pay | 1 198 | Regular Pay | 2 198 | Afternoon shift | 3 198 | Afternoon shift | 4 198 | OT | 5 198 | OT | 6 198 | EVENING SHIFT | 7 198 | EVENING SHIFT | 8 11 | Regular Pay | 11 11 | Regular Pay | 12 11 | TL | 13 11 | TL | 14 11 | EVENING SHIFT | 15 11 | EVENING SHIFT | 16 12 | TL | 21 12 | TL | 22 12 | EVENING SHIFT | 23 12 | EVENING SHIFT | 24
select person_id, ot, regular_pay, elements as other_code, mes as other_measure from ( /*First you need to aggregate all the measures by person_id and code*/ select person_id, elements, sum(measure) as mes from t /*Date filter goes here*/ group by person_id, elements ) model /*RETURN UPDATED ROWS will do the trick, because we'll update only "other" measures, so OT and Regular pay will no go to the output*/ return updated rows /*Where to break the calculation*/ partition by (person_id) /*To be able to reference by code*/ dimension by (elements) measures ( mes, 0 as ot, 0 as regular_pay ) rules upsert ( ot[ elements not in ('OT', 'Regular Pay') ] = sum(mes)['OT'], regular_pay[ elements not in ('OT', 'Regular Pay') ] = sum(mes)['Regular Pay'] )
PERSON_ID | OT | REGULAR_PAY | OTHER_CODE | OTHER_MEASURE --------: | ---: | ----------: | :-------------- | ------------: 198 | 11 | 3 | EVENING SHIFT | 15 198 | 11 | 3 | Afternoon shift | 7 11 | null | 23 | TL | 27 11 | null | 23 | EVENING SHIFT | 31 12 | null | null | TL | 43 12 | null | null | EVENING SHIFT | 47
db<>fiddle here