How to limit return results - sql

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

Related

Count of consecutive days ORACLE SQL

I need help with a query where a need to count de consecutive days like this
select
a.numcad, a.datapu , f.datapu , nvl(to_char(f.datapu, 'DD'),0)dia,
row_number() over (partition by a.numcad, f.datapu order by f.datapu)particao
from
ronda.r066apu a
left join (select t.numcad, t.numemp, t.datacc, t.datapu
from ronda.r070acc t
where t.datacc >= '21/01/2022'
and t.datacc <= trunc(sysdate)
group by t.numcad, t.numemp, t.datacc, t.datapu)f
on a.numemp = f.numemp
and a.numcad = f.numcad
and a.datapu = f.datapu
where a.numcad = 2675
and A.DATAPU >= '21/01/2022'
and A.DATAPU <= trunc(sysdate)
group by a.numcad, a.datapu, f.datapu, f.datacc
order by a.datapu
result is
between 24/01/2022 and 04/02/2022
is 12 days i need know this count , but i will ways get the '21/mes/year'
You can try:
SELECT TO_DATE('2022-01-24', 'YYYY-MM-DD') -
TO_DATE('2022-02-04', 'YYYY-MM-DD')
FROM dual
This returns 21, for example...

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

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

Oracle SQL - Generate rows based on quantity column

We use pooled positions that have a max headcount assigned and I need to build a report that creates a line for each head, including the details of the incumbent if there is one or a NULL line where there is a vacancy.
Like this:
Position_Title
Headcount
Incumbent
Analyst
3
Employee1
Analyst
3
Employee2
Analyst
3
I can join the Person/Assignment tables with the Position table to generate a separate line where there is an incumbent but the part i'm struggling with, is generating a line where there is a vacancy.
I spotted another post on here that suggested using connect by but I can't get it to work.
It seems to work on its own like this:
SELECT
HAP.NAME POSITION_TITLE,
HAP.POSITION_CODE,
HAP.ACTIVE_STATUS,
HAP.POSITION_TYPE,
HAP.FTE,
LEVEL row_num
FROM
HR_ALL_POSITIONS_F_VL HAP
CONNECT BY LEVEL <= HAP.FTE
AND PRIOR HAP.POSITION_ID = HAP.POSITION_ID
AND PRIOR sys_guid() IS NOT NULL
But I'm not sure how to use it with the rest of my query (I've tried using the WHERE clause before and after the CONNECT BY but it times out either way)
SELECT
HAP.NAME POSITION_TITLE,
HAP.POSITION_CODE,
PGF.NAME GRADE_NAME,
PGF.GRADE_CODE,
HAP.ACTIVE_STATUS,
HAP.POSITION_TYPE,
HAP.HEADCOUNT,
PAAM.ASSIGNMENT_NUMBER,
LEVEL row_num
FROM
HR_ALL_POSITIONS_F_VL HAP,
PER_GRADES_F_VL PGF,
PER_ALL_ASSIGNMENTS_M PAAM
WHERE
HAP.ENTRY_GRADE_ID = PGF.GRADE_ID
AND PAAM.POSITION_ID(+) = HAP.POSITION_ID
AND TRUNC(Sysdate) between HAP.effective_start_date AND HAP.effective_end_date
AND TRUNC(Sysdate) between PGF.effective_start_date AND PGF.effective_end_date
AND PAAM.effective_start_date(+) <= TRUNC(Sysdate)
AND PAAM.effective_end_date(+) >= TRUNC(Sysdate)
CONNECT BY LEVEL <= HAP.HEADCOUNT
AND PRIOR HAP.POSITION_ID = HAP.POSITION_ID
AND PRIOR sys_guid() IS NOT NULL
You can use multiset to generate rows as per the headcount column as follows:
SELECT
HAP.NAME POSITION_TITLE,
HAP.POSITION_CODE,
PGF.NAME GRADE_NAME,
PGF.GRADE_CODE,
HAP.ACTIVE_STATUS,
HAP.POSITION_TYPE,
HAP.HEADCOUNT,
PAAM.ASSIGNMENT_NUMBER,
Lvls.Column_value row_num
FROM
HR_ALL_POSITIONS_F_VL HAP,
PER_GRADES_F_VL PGF,
PER_ALL_ASSIGNMENTS_M PAAM,
table(cast(multiset(select level from dual connect by level <= hap.headcount) as sys.OdciNumberList)) lvls
WHERE
HAP.ENTRY_GRADE_ID = PGF.GRADE_ID
AND PAAM.POSITION_ID(+) = HAP.POSITION_ID
AND TRUNC(Sysdate) between HAP.effective_start_date AND HAP.effective_end_date
AND TRUNC(Sysdate) between PGF.effective_start_date AND PGF.effective_end_date
AND PAAM.effective_start_date(+) <= TRUNC(Sysdate)
AND PAAM.effective_end_date(+) >= TRUNC(Sysdate);
Note: add the condition as per your requirement and always use standard ANSI joins.

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;

Combine 2 sql queries into one with eliminating duplicate colums

I have written 2 sql queries by using multiple join statements.
Now I want to combine both the query results as below.
First query shows these columns
UDC_ID, EXT_ID, VALUE
The second query shows these columns
UDC_ID, EXT_ID, VALUE
In both the queries UDC_ID and EXT_ID columns are the same, but the VALUE column in each is different
So the final output I want to display is,
UDC_ID, EXT_ID, VALUE (From Query1), VALUE (from Query 2)
Can anyone suggest how this can be achieved?
These are my queries:
Query 1 joins three tables:
SELECT
DEV.UDC_ID,
SR.EXT_ID,
SRA.VALUE
FROM SERVICE_REQUEST SR
JOIN DEVICE DEV
ON SR.DEVICE_ID = DEV.ID
JOIN SERVICE_REQUEST_ATTR SRA
ON SR.ID = SERVICE_REQUEST_ID
WHERE SR.SUB_TYPE_CD = 'HMI_22'
--AND DEV.SUB_TYPE = 'ESME'
AND SRA.NAME = 'CommsHubGUID'
AND SR.INSERT_TIME >= TO_DATE('2016-09-21 00:00:00', 'YYYY-MM-DD HH24:MI:SS')
AND SR.INSERT_TIME <= TO_DATE('2016-09-28 00:00:00', 'YYYY-MM-DD HH24:MI:SS')
ORDER BY SR.INSERT_TIME DESC;
The difference between query 1 and this query is the where clause criterion for SRA.NAME field, otherwise both the queries are same.
SELECT
DEV.UDC_ID,
SR.EXT_ID,
SRA.VALUE
FROM SERVICE_REQUEST SR
JOIN DEVICE DEV
ON SR.DEVICE_ID = DEV.ID`enter code here`
JOIN SERVICE_REQUEST_ATTR SRA
ON SR.ID = SERVICE_REQUEST_ID
WHERE SR.SUB_TYPE_CD = 'HMI_22'
--AND DEV.SUB_TYPE = 'ESME'
AND SRA.NAME = 'Service Location'
AND SR.INSERT_TIME >= TO_DATE('2016-09-21 00:00:00', 'YYYY-MM-DD HH24:MI:SS')
AND SR.INSERT_TIME <= TO_DATE('2016-09-28 00:00:00', 'YYYY-MM-DD HH24:MI:SS')
ORDER BY SR.INSERT_TIME DESC
SELECT COALESCE(q1.UDC_ID,q2.UDC_ID),
COALESCE(q1.EXT_ID, q2.EXT_ID),
q1.VALUE ,
q2.VALUE
FROM (query 1) q1
FULL OUTER JOIN (query 2) q2 ON q1.UDC_ID=q2.UDC_ID and q1.EXT_ID=q2.EXT_ID