SQL query to get the data as of 31/03 of past three years - sql

I have created the above query which give me the Bonus tagged to the person as of sysdate.
select
person_number ,
peef.effective_start_Date,
peef.value Amount
from
per_all_people_f papf,
pay_element_entries_f peef
where
papf.person_id = peef.person_id
and PEEF.element_name in ('Bonus')
and sysdate between peef.effective_start_Date and peef.effective_end_Date
I want to tweak the above query to get the Amount for past three years as of 31/3 i.e. instead of sysdate as of 31/3/2021, 31/03/2020,31/03/2019
Output like -
Person_NUMBER effective_start_Date current_Amount 2021_AMOUNT 2020_AMOUNT 2019_AMOUNT
How can i tweak the same query and change the sysdate condition to look for data for past three years as well for the 2021_amount, 2020_amount and 2019_amount column

You can move the last line to the SELECT list as conditionals such as
SELECT person_number, peef.effective_start_Date,
peef.value AS current_amount,
CASE WHEN date'2021-03-31' BETWEEN peef.effective_start_Date AND peef.effective_end_Date
THEN peef.value
END AS 2021_amount,
CASE WHEN date'2020-03-31' BETWEEN peef.effective_start_Date AND peef.effective_end_Date
THEN peef.value
END AS 2020_amount,
CASE WHEN date'2019-03-31' BETWEEN peef.effective_start_Date AND peef.effective_end_Date
THEN peef.value
END AS 2019_amount
FROM per_all_people_f papf
JOIN pay_element_entries_f peef
ON peef.person_id = papf.person_id
WHERE peef.element_name = 'Bonus'
in order to get the currently displayed result, but in this case there will be multiple lines with NULL values for amount columns. I suspect that you need to get aggregated results in order to show the summed up amounts, then consider adding SUM() aggregation such as
SELECT person_number, peef.effective_start_Date,
SUM( peef.value ) AS current_amount,
SUM( CASE WHEN date'2021-03-31' BETWEEN peef.effective_start_Date AND peef.effective_end_Date
THEN peef.value
END ) AS 2021_amount,
SUM( CASE WHEN date'2020-03-31' BETWEEN peef.effective_start_Date AND peef.effective_end_Date
THEN peef.value
END ) AS 2020_amount,
SUM( CASE WHEN date'2019-03-31' BETWEEN peef.effective_start_Date AND peef.effective_end_Date
THEN peef.value
END ) AS 2019_amount
FROM per_all_people_f papf
JOIN pay_element_entries_f peef
ON peef.person_id = papf.person_id
WHERE peef.element_name = 'Bonus'
GROUP BY person_number, peef.effective_start_Date

Related

Combine like lines based off of date

I'm having trouble finishing this query. The end result I'm looking for is:
I have so far wrote this query:
SELECT
to_char(favi.date::date, 'mm-dd-yyyy') AS "Date",
(SELECT COUNT(dv.severity) WHERE dv.severity='Critical') AS "Critical Vulns",
(SELECT COUNT(dv.severity) WHERE dv.severity='Severe') AS "Severe Vulns",
(SELECT COUNT(dv.severity) WHERE dv.severity='Moderate') AS "Moderate Vulns",
COUNT(favi.asset_id) AS "Asset Count"
FROM fact_asset_vulnerability_instance favi
JOIN dim_vulnerability dv ON dv.vulnerability_id=favi.vulnerability_id
GROUP BY to_char(favi.date::date, 'mm-dd-yyyy'), dv.severity
ORDER BY to_char(favi.date::date, 'mm-dd-yyyy')
My results though are:
How exactly do I combine the rows on the date? The results split the date into three rows each one displaying the actual count for whatever severity it is. I just want one row per date that shows each of the severity values on one line.
I've played around with UNION, DISTINCT, FULL JOIN, etc but this is slightly past my knowledge of how to get the desired results.
The below code is what ended up working.
SELECT
to_char(favi.date::date, 'mm-dd-yyyy') AS "Date",
SUM(CASE WHEN dv.severity = 'Critical' THEN 1 END) AS "Critical Vulns",
SUM(CASE WHEN dv.severity = 'Severe' THEN 1 END) AS "Severe Vulns",
SUM(CASE WHEN dv.severity = 'Moderate' THEN 1 END) AS "Moderate Vulns",
COUNT(favi.asset_id) AS "Asset Count"
FROM fact_asset_vulnerability_instance favi
JOIN dim_vulnerability dv ON dv.vulnerability_id=favi.vulnerability_id
GROUP BY to_char(favi.date::date, 'mm-dd-yyyy')
ORDER BY to_char(favi.date::date, 'mm-dd-yyyy')
so by doing the SUM function as #SOS mentioned I was able to drop the GROUP BY on dv.severity

SQL query to use group by to get the sum of two different columns within a date range

I have two tables time track and absence for an employee.
person_number Measure start_Date end_date Time_type
73636 10 01-Jan-2020 02-Jan-2020 Double
73636 24 06-Jan-2020 08-jan-2020 Double
73636 10 15-Jan-2020 25-Jan-2020 Regular Pay
73636 11.9 06-Jan-2020 08-jan-2020 Double
73636 27 10-Jan-2020 15-Jan-2020 Regular Pay
Absence det
person_number start_Date end_date duration Absence_type
73636 05-Jan-2020 10-Jan-2020 10 Vacation
73636 06-Jan-2020 18-jan-2020 9 Paid Leave
73636 20-Jan-2020 21-jan-2020 1 Paid Leave
Now when i pass the from and to date as 01-Jan-2020 and 31-Jan-2020, the output should look like -
Person_Number Double Regular Hour_code hour_amount
73636 31.9 37 Paid Leave 10
The hour_code should have only "Paid Leave" and no other absences
Now I have written the below query for this
SELECT
distinct person_number,
sum(
CASE
WHEN elements = 'Double' THEN measure
END
) AS OT_Hours,
sum(
CASE
WHEN elements LIKE 'Regular Pay%' THEN measure
END
) AS regular_measure_hours,
sum(
CASE
WHEN absence_name IN ('Paid Leave') THEN absence_duration
END
) AS hour3_amount,
max(
CASE
WHEN absence_name IN ('Paid Leave') THEN 'Paid Leave'
END
) AS hour3_code
FROM
(
select
person_number,
Time_type elements,
Absence_type absence_name,
duration,
measure
from
time_track_tab,
abs_tab,
per_all_people_F papf
where
time_track_tab.person_id = abs_tab.person_id
and abs_tab.person_id = papf.person_id
and abs_tab.Absence_type = 'Paid Leave'
)
group by
person_number
This is giving me multiple row output and calculation of sum is not coming correctly as in between the to and from date there are different dates present for both absence and time track.
My requirement is to calculate the sum of ALL the duration and measure column within these parameter dates. How can i tweak my query to get the correct sum between these dates ?
Is there a way to use partition by or group by or anything else to calculation these correctly in the column
You probably need to group both tables first then join them together to avoid the cross join.
select person_number, TimeTrack.DoublePay, TimeTrack.Regular,
Absenses.Hour_code, Absenses.hour_amount from
per_all_people_F papf,
(select
person_id, sum(duration) as hour_amount, Absence_type as Hour_code
from
abs_tab
where
abs_tab.Absence_type = 'Paid Leave'
and
start_Date between '2020-01-01' and '2020-01-31'
group by person_id,Absence_type
) Absenses,
(select
person_id,
sum(case when Time_type = 'Double' then Measure end) as DoublePay,
sum(case when Time_type = 'Regular Pay' then Measure end) as Regular
from time_track_tab
where
start_Date between '2020-01-01' and '2020-01-31'
group by person_id
) TimeTrack
where
papf.person_id = TimeTrack.person_id
and
papf.person_id = Absenses.person_id
and
papf.person_id = 73636
I made a SqlFiddle if you want to play with it
http://sqlfiddle.com/#!9/03e460/36
Also my 2 cents; I'd recommend left outer joining from the per_all_people_F table or else people without absenses will get filtered out.
See if, what you need is something like this:
select * from
(SELECT person_number,
sum(
CASE
WHEN Time_type = 'Double' THEN measure
END
) AS Double,
sum(
CASE
WHEN Time_type = ('Regular Pay') THEN measure
END
) AS regular
from time_track_tab
group by person_number
) A
inner join
(SELECT
person_number,
sum(
CASE
WHEN Absence_type = 'Vacation' THEN duration
END
) AS Vacation,
sum(
CASE
WHEN Absence_type = ('Paid Leave') THEN duration
END
) AS paidLeave
from abs_tab
group by person_number
)B on A.person_number = B.person_number
here the fiddle:
http://sqlfiddle.com/#!4/21253/2

Select Max date column in a sql query, which is joined to other columns

I have an Oracle Query below
select papf.person_number, to_char(hrcd.SUBMITTED_DATE, 'DD-Mon-YYYY','NLS_DATE_LANGUAGE = American') as "Resignation Date", paam.last_update_date as assignmentupdate, hrcd.last_update_date as hrcdupdate, hth.last_update_date as hthupdate
from
per_all_people_f papf, per_all_assignments_m paam, hrc_txn_header hth, HRC_TXN_DATA hrcd
where
papf.person_id=paam.person_id
and paam.assignment_type IN ('E','C')
and paam.assignment_status_type in ('ACTIVE')
and paam.primary_flag = 'Y'
and paam.EFFECTIVE_LATEST_CHANGE ='Y'
and trunc(sysdate) between trunc(paam.effective_start_date) and trunc(paam.effective_end_date)
and trunc(sysdate) between trunc(papf.effective_start_date) and trunc(papf.effective_end_date)
and paam.person_id=hth.subject_id(+)
and paam.assignment_id=hth.object_id(+)
and hth.module_identifier(+) IN ('Resignation','Terminations')
and hrcd.transaction_id(+)=hth.transaction_id
and papf.person_number IN ('901626', '900723', '900846');
Which is giving below result
Now I am Person 900846 has multiple rows coming, now I need to extract the max date from this column for that I added the below logic but this is not working
select papf.person_number, to_char(hrcd.SUBMITTED_DATE, 'DD-Mon-YYYY','NLS_DATE_LANGUAGE = American') as "Resignation Date", paam.last_update_date as assignmentupdate, hrcd.last_update_date as hrcdupdate, hth.last_update_date as hthupdate
from
per_all_people_f papf, per_all_assignments_m paam, hrc_txn_header hth, HRC_TXN_DATA hrcd
where
papf.person_id=paam.person_id
and paam.assignment_type IN ('E','C')
and paam.assignment_status_type in ('ACTIVE')
and paam.primary_flag = 'Y'
and paam.EFFECTIVE_LATEST_CHANGE ='Y'
and trunc(sysdate) between trunc(paam.effective_start_date) and trunc(paam.effective_end_date)
and trunc(sysdate) between trunc(papf.effective_start_date) and trunc(papf.effective_end_date)
and paam.person_id=hth.subject_id(+)
and paam.assignment_id=hth.object_id(+)
and hth.module_identifier(+) IN ('Resignation','Terminations')
and hrcd.transaction_id(+)=hth.transaction_id
and hrcd.SUBMITTED_DATE =
(SELECT MAX(hrcd2.SUBMITTED_DATE)
FROM HRC_TXN_DATA hrcd2, hrc_txn_header hth2, per_all_assignments_m paam2
WHERE hrcd2.TRANSACTION_ID = hrcd.TRANSACTION_ID
AND hrcd2.transaction_id=hth2.transaction_id
and hth2.module_identifier IN ('Resignation','Terminations')
and paam2.assignment_id=hth2.object_id
and paam2.assignment_id=paam.assignment_id
)
and papf.person_number IN ('901626', '900723', '900846');
But now the Output is like below
I am not sure how the outer join will be added in the second query and even after after that the result should 3 lines of data each for employee with max resignation date and blank is resignation date is null
Output should look like below
can someone help me in this?
Thanks,
Shivam
You can use window functions (ROW_NUMBER | RANK | DENSE_RANK | MAX OVER) to rank your rows and only pick the latest per person. E.g.:
select person_number, "Resignation Date", assignmentupdate, hrcdupdate, hthupdate
from
(
select
papf.person_number,
to_char(hrcd.submitted_date, 'DD-Mon-YYYY', 'NLS_DATE_LANGUAGE = American') as "Resignation Date",
paam.last_update_date as assignmentupdate,
hrcd.last_update_date as hrcdupdate,
hth.last_update_date as hthupdate,
hrcd.submitted_date,
max(hrcd.submitted_date) over (partition by papf.person_number) as max_submitted_date
from per_all_people_f papf
join per_all_assignments_m paam on paam.person_id = papf.person_id
left join hrc_txn_header hth on hth.subject_id = paam.person_id
and hth.object_id = paam.assignment_id
and hth.module_identifier IN ('Resignation', 'Terminations')
left join HRC_TXN_DATA hrcd on hrcd.transaction_id = hth.transaction_id
where papf.person_number IN (901626, 900723, 900846)
and paam.assignment_type IN ('E', 'C')
and paam.assignment_status_type in ('ACTIVE')
and paam.primary_flag = 'Y'
and paam.effective_latest_change = 'Y'
and trunc(sysdate) between trunc(paam.effective_start_date) and trunc(paam.effective_end_date)
and trunc(sysdate) between trunc(papf.effective_start_date) and trunc(papf.effective_end_date)
)
where (submitted_date = max_submitted_date)
or (submitted_date is null and max_submitted_date is null)
order by person_number;

How to limit return results

My query returns duplicate rows and I want to return only one row.
select papf.Full_Name,
papf.Employee_number,
papf.DatE_OF_BIRTH,
peef.last_update_date
/*,
petf1.ELEMENT_NAME as MedicalSchemeName*/
from per_all_people_f papf
,per_all_assignments_f paaf
,PAY_ELEMENT_ENTRIES_F peef
,pay_element_types_f petf
--,fnd_user fnu
where (papf.Employee_number) not in
(select
papf1.Employee_number
from per_all_people_f papfinner
,per_all_assignments_f paafinner
,PAY_ELEMENT_ENTRIES_F peefinner
,pay_element_types_f petfinner
where paafinner.person_id = papfinner.person_id
and peefinner.assignment_id = paafinner.assignment_id
and peefinner.element_type_id = petfinner.element_type_id
and upper(petf1.ELEMENT_NAME) like '%Condition%'
and SYSDATE BETWEEN papfinner.EFFECTIVE_START_DATE AND papfinner.EFFECTIVE_END_DATE
and SYSDATE BETWEEN paafinner.EFFECTIVE_START_DATE AND paafinner.EFFECTIVE_END_DATE
and SYSDATE BETWEEN peefinner.EFFECTIVE_START_DATE AND peefinner.EFFECTIVE_END_DATE
and SYSDATE BETWEEN petfinner.EFFECTIVE_START_DATE AND petfinner.EFFECTIVE_END_DATE
)
and SYSDATE BETWEEN papf.EFFECTIVE_START_DATE AND papf.EFFECTIVE_END_DATE
and SYSDATE BETWEEN paaf.EFFECTIVE_START_DATE AND paaf.EFFECTIVE_END_DATE
and SYSDATE BETWEEN peef.EFFECTIVE_START_DATE AND peef.EFFECTIVE_END_DATE
and SYSDATE BETWEEN petf.EFFECTIVE_START_DATE AND petf.EFFECTIVE_END_DATE
and upper(petf.ELEMENT_NAME) not like '%Condition%'
and rownum <= 10000
order by peef.last_update_date;
....
This query works properly and returns the correct results but the results are duplicated. I only need one unique row
One of the tables you are joining one is returning doubles or more. I bet it is "peef". Perhaps you can only show the MAX(last_update_date) and roll the rest up against that. So just GROUP BY.
select papf.Full_Name,
papf.Employee_number,
papf.DatE_OF_BIRTH,
last_update_date = MAX(peef.last_update_date)
...
GROUP BY
papf.Full_Name,
papf.Employee_number,
papf.DatE_OF_BIRTH

Presto SQL full outer join

I've got a full join that isn't working like how I expected it to.
I'm joining on 4 columns. However, one of the columns has some blank values, causing some numbers to come up[ unjoint. When I take this column out, the query works. However, I have to have this certain column for the report as it's how we are reporting on the numbers.
Query in question: (the column that doesn't work is the OM.line_item_id)
SELECT DBM.dated, DBM.line_item, DBM.line_item_id, DBM.insertion_order, DBM.insertion_order_id, DBM.device_type, DBM.market, DBM.impressions, DBM.clicks, DBM.amount_spent_EUR, OM.orders, OM.revenue, OM.device
FROM
(
SELECT
DATE_FORMAT(DATE_PARSE(date,'%Y/%m/%d'),'%Y-%m-%d') AS dated, line_item, line_item_id, insertion_order, insertion_order_id, device_type, trim(SPLIT_PART(insertion_order,'|',3)) AS market, cast(impressions as double) as impressions, cast(clicks as double) as clicks, CAST(media_cost_advertiser_currency AS DOUBLE)*1.15 AS amount_spent_EUR
FROM ralph_lauren_google_sheet_dbm_data
WHERE dated >= '2019-03-31'
AND dated <= {{days_ago 1}}
GROUP BY 1,2,3,4,5,6,7,8,9,10
)DBM
FULL outer JOIN
(
SELECT dated, line_item_id, device, market, sum(orders) as orders, sum(revenue)+sum(shipping_revenue)-sum(coupon_discount) as revenue
FROM
(
select
dated,
utm_content_v21 as line_item_id,
order_currency_code_v33_evar33,
case lower(mobile_device_type)
when 'other' then 'Desktop'
when 'tablet' then 'Tablet'
when 'mobile phone' then 'Smart Phone'
else 'Other'
End as device,
case geosegmentation_countries
when 'united kingdom' then 'UK'
when 'germany' then 'DE'
when 'france' then 'FR'
when 'italy' then 'IT'
when 'spain' then 'ES'
else 'other'
end as market,
sum(cast(orders as bigint))as orders,
case
WHEN lower(order_currency_code_v33_evar33) LIKE '%gbp%' THEN sum(TRY_CAST(revenue AS DOUBLE)*1.15)
ELSE Sum(TRY_CAST(revenue AS DOUBLE)*1)
END as revenue,
CASE
WHEN lower(order_currency_code_v33_evar33) LIKE '%gbp%' THEN sum(TRY_CAST(order_level_shipping_revenue_e62_event62 AS DOUBLE)*1.15)
ELSE sum(TRY_CAST(order_level_shipping_revenue_e62_event62 AS DOUBLE)*1)
END as shipping_revenue,
CASE
WHEN lower(order_currency_code_v33_evar33) LIKE '%gbp%' THEN sum(TRY_CAST(order_level_coupon_discount_e77_event77 AS DOUBLE)*1.15)
ELSE sum(TRY_CAST(order_level_coupon_discount_e77_event77 AS DOUBLE)*1)
END as coupon_discount
from ralph_lauren_ftp_all_eu_markets_ltc
WHERE dated >= '2019-03-31'
AND dated <= {{days_ago 1}}
and last_touch_channel like 'Retargeting'
and lower(utm_medium_v21) not like '%fbig%'
and cast(orders as bigint) > 0
group by
1,2,3,4,5
)
GROUP BY
1,2,3 ,4-- revenue numbers are getting duplicated for some reason
)OM
ON
DBM.dated = OM.dated AND DBM.line_item_id = OM.line_item_id and DBM.device_type = OM.device AND DBM.market = OM.market
wouldn't a full outer join allow me to join up numbers if they have the other three columns being joint up?
thanks