Sql query - Oracle database - sql

empid emplrcd effdt effsq
101 #1 2/1/99 0
101 #1 3/1/13 1
101 #1 23/3/13 1
101 #1 22/6/13 2
102 #2 20/6/91 1
I need to retrieve row 4, and I have written a partial code, please help me with the other half.
select a*
from Ps_Job a
where a.empid = '101'
and a.emprcd ='#1'
and a.effdt = (select max(a1.effdt) from Psjob1) where...............
and a.effseq = (Select max(a2.effseq) from Ps_job2)
where..............
Please help me with the where caluse which should be generic and not row specific. i think it should be filled with nth max concept but not sure.

In oracle
select *
from
(select a* from Ps_Job a
where a.empid = '101'
and a.emprcd ='#1'
and a.effdt = (select max(a1.effdt) from Psjob1) where ...
and a.effseq = (Select max(a2.effseq) from Ps_job2)
where ..... )
where ROWNUM == **The line number what you want to get**;
In sql
SELECT * from Ps_Job LIMIT 3,1where(
select a* from Ps_Job a
where a.empid = '101'
and a.emprcd ='#1'
and a.effdt = (select max(a1.effdt) from Psjob1) where ...
and a.effseq = (Select max(a2.effseq) from Ps_job2)
where ..... )

Related

Display only 1 row in unioned query where they have rows certain criteria in another table

I couldn't think of a better title to this thread but I have the below Unioned query that is pulling in exam information per UserID that is unioned to pull in the total of the counts.
The problem is that when the UserID has two rows in PS_JOB AND one row has a PER_ORG value of 'CWR' and the other row has a PER_ORG value of 'EMP' then the query is returning 2 rows for this same UserID. In this scenario I only want to display the 'EMP' record, so that only 1 instance of their ID (that falls into this scenario) will count in my Totals (ZTOTAL).
I imagine I need some sort of WHERE condition with NOT EXISTS where it finds two rows with the same UserID, AND one row contains PER_ORG = 'EMP' and the other row contains PER_ORG = 'CWR', but am struggling as to how to code this. I don't want to exclude USERID's that have two rows in PS_JOB with any other combination of values for PER_ORG, other than 'EMP' and 'CWR'.
Current SQL:
SELECT
A.USERID,
A.IMMUN_CODE,
B.COMPANY,
COUNT(*) AS 'COUNT_OF_EXAMS'
FROM
PS_HS_IMMUN A,
PS_JOB B,
PS_EMPLMT_SRCH_QRY B1
WHERE
(B.USERID = B1.USERID
AND B.EMPL_RCD = B1.EMPL_RCD
AND B1.OPRID = 'GG125'
AND ( A.USERID = B.USERID
AND B.EFFDT = (SELECT MAX(B_ED.EFFDT)
FROM PS_JOB B_ED
WHERE B.USERID = B_ED.USERID
AND B.EMPL_RCD = B_ED.EMPL_RCD
AND B_ED.EFFDT <= SUBSTRING(CONVERT(CHAR,GETDATE(),121), 1, 10))
AND B.EFFSEQ = (SELECT MAX(B_ES.EFFSEQ)
FROM PS_JOB B_ES
WHERE B.USERID = B_ES.USERID
AND B.EMPL_RCD = B_ES.EMPL_RCD
AND B.EFFDT = B_ES.EFFDT)
)
)
AND A.HISTORY_ONLY <> 'Y'
GROUP BY A.USERID, A.IMMUN_CODE, B.COMPANY
UNION
SELECT
'ZTOTAL',
'',
'',
COUNT ( D.USERID)
FROM
(PS_HS_IMMUN D
LEFT OUTER JOIN
(PS_JOB E
INNER JOIN PS_EMPLMT_SRCH_QRY E1 ON
(E.USERID = E1.USERID
AND E.EMPL_RCD = E1.EMPL_RCD
AND E1.OPRID = 'GG125' )) ON
D.USERID = E.USERID)
WHERE
(
(E.EFFDT = (SELECT MAX(E_ED.EFFDT)
FROM PS_JOB E_ED
WHERE E.USERID = E_ED.USERID
AND E.EMPL_RCD = E_ED.EMPL_RCD
AND E_ED.EFFDT <= SUBSTRING(CONVERT(CHAR,GETDATE(),121), 1, 10))
AND E.EFFSEQ = (SELECT MAX(E_ES.EFFSEQ)
FROM PS_JOB E_ES
WHERE E.USERID = E_ES.USERID
AND E.EMPL_RCD = E_ES.EMPL_RCD
AND E.EFFDT = E_ES.EFFDT)
--AND D.EXAM_DT BETWEEN :1 AND :2
--AND E.COMPANY = :3
AND D.HISTORY_ONLY <> 'Y' )
)
Current Results From Above Query:
In this example, the two rows for UserID 4992 is duplicated because the UserID has two rows in the PS_JOBS table, hence why the USERID displays twice (and ultimately counts twice in the totals) in the query.
If I do a query from PS_JOBS for this USERID, you will see the two rows for this USERID AND the PER_ORG status of 'EMP' and 'CWR', respectfully.
SELECT *
FROM PS_JOB
WHERE EMPLID = '4992'
Results from above query:
I'm looking to avoid using Common Table Expressions as a solution. Thanks for any suggestions!

SQL Select only unique values in column

I have the below query that is pulling from a table where a record (Employee ID) can have more than 1 row of data. Because of this I have some rows with the highest (Max) EXAM_DATE. I have added in the MAX function into the SELECT Statement, however I am still retrieving rows with 2 or more dates per empl. This must be something simply that I am overlooking. Any help is appreciated.
SQL Query:
SELECT A.EMPLID, A.BUSINESS_TITLE, A.DEPTID, A.LOCATION, A.LAST_NAME,
A.FIRST_NAME, A.MIDDLE_NAME,
MAX(CONVERT(CHAR(10),D.EXAM_DT,121))AS EXAM_DATE, D.EXAM_TYPE_CD,
(CONVERT(CHAR(10),D.GH_EXPIRE_DATE,121)) AS EXPIRE_DATE, AA.NAME AS
Manager_Name
FROM ((PS_EMPLOYEES A INNER JOIN PS_EMPLMT_SRCH_QRY A1 ON (A.EMPLID =
A1.EMPLID AND A.EMPL_RCD = A1.EMPL_RCD AND A1.OPRID = 'HD065' ))
LEFT OUTER JOIN PS_GHS_HS_PPDSCRN D ON A.EMPLID = D.EMPLID)
--LEFT OUTER JOIN PS_GHS_REPORTS_TO H ON A.EMPLID = H.EMPLID
LEFT OUTER JOIN PS_EMPLOYEES AA ON AA.POSITION_NBR = A.REPORTS_TO
AND (( AA.EFFDT =
(SELECT MAX(A_ED.EFFDT) FROM PS_EMPLOYEES A_ED
WHERE AA.POSITION_NBR = A_ED.POSITION_NBR
AND A_ED.EFFDT <= SUBSTRING(CONVERT(CHAR,GETDATE(),121), 1, 10)) ))
WHERE ( ( A.EFFDT =
(SELECT MAX(A_ED.EFFDT) FROM PS_EMPLOYEES A_ED
WHERE A.EMPLID = A_ED.EMPLID
AND A.EMPL_RCD = A_ED.EMPL_RCD
AND A_ED.EFFDT <= SUBSTRING(CONVERT(CHAR,GETDATE(),121), 1, 10))
AND A.EFFSEQ =
(SELECT MAX(A_ES.EFFSEQ) FROM PS_EMPLOYEES A_ES
WHERE A.EMPLID = A_ES.EMPLID
AND A.EMPL_RCD = A_ES.EMPL_RCD
AND A.EFFDT = A_ES.EFFDT)
AND D.EXAM_TYPE_CD = 'PPD'))
AND A.EMPL_STATUS = 'A'
--AND NOT EXISTS (SELECT D.EMPLID, COUNT(*) AS 'TotalOccur' FROM PS_GHS_HS_PPDSCRN D GROUP BY D.EMPLID HAVING COUNT(*) > 1)
GROUP BY A.EMPLID, A.BUSINESS_TITLE, A.DEPTID, A.LOCATION, A.LAST_NAME,
A.FIRST_NAME, A.MIDDLE_NAME, D.EXAM_TYPE_CD, D.GH_EXPIRE_DATE, AA.NAME
ORDER BY 5
I tried running it with the Commented out code for NOT EXISTS, however when I run this I do not retrieve any results.
Sample Output:
The MAX in your WHERE should be fine.
Your EXPIRE_DATE is also different between the two records, and as the EXPIRE_DATE is included in the GROUP BY, it will cause the "duplicate".

count after join on multiple tables and count of multiple column values

Please help me with below problem.
table 1 employee details
emp name empno.
---------------------------------
John 1234
Joe 6789
table 2 employee assignment
empno assignmentstartdate assignmentenddate assignmentID empassignmentID
-----------------------------------------------------------------------------
1234 01JAN2017 02JAN2017 A1 X1
6789 01jan2017 02JAN2017 B1 Z1
table 3 employee assignment property
empassignmentID assignmentID propertyname propertyvalue
-------------------------------------------------------------------
X1 A1 COMPLETED true
X1 A1 STARTED true
Z1 B1 STARTED true
Z1 B1 COMPLETED false
Result wanted: (count of completed and started for each employee)
emp name emp no. COMPLETED STARTED
------------------------------------------
John 1234 1 1
Joe 6789 0 1
Currently with my query it is not putting count correctly for propertyvalue if I run for one employee it works correctly but not for multiple employees.
Please help.
SELECT empno ,
empname ,
(SELECT COUNT(A.propertyvalue)
FROM employeedetails C ,
employees_ASSIGNMENT RCA,
employee_assignment_property A
WHERE TRUNC(startdate) >= '14jun2017'
AND TRUNC(endate) <= '20jun2017'
AND RCA.empno = C.empno
AND RCA.empassignmetid = A.empassignmetid
AND rca.EMPNO IN ('1234','6789')
AND RCA.assignmentid = A.assignmentid
AND A.Name = 'COMPLETED'
AND A.propertyvalue = 'true') ,
(SELECT COUNT(A.propertyvalue)
FROM employeedetails C ,
employees_ASSIGNMENT RCA,
employee_assignment_property A
WHERE TRUNC(startdate) >= '14jun2017'
AND TRUNC(endate) <= '20jun2017'
AND RCA.empno = C.empno
AND RCA.empassignmetid = A.empassignmetid
AND rca.EMPNO IN ('1234','6789')
AND RCA.assignmentid = A.assignmentid
AND A.Name = 'STARTED'
AND A.propertyvalue = 'true')FROM employeedetails WHERE EMPNO IN
('1234','6789') GROUP BY C.empno ,
C.EMPNAME
I think you are simply looking for this:
SELECT DET.empname
, COUNT(CASE WHEN PROP.propertyname = 'COMPLETED' THEN 1 END) COMP_COUNT
, COUNT(CASE WHEN PROP.propertyname = 'STARTED' THEN 1 END) START_COUNT
FROM employeedetails DET
INNER JOIN employees_ASSIGNMENT ASS
ON ASS.empno = DET.empno
INNER JOIN employee_assignment_property PROP
ON PROP.empassignmentID = ASS.empassignmentID
AND PROP.assignmentID = ASS.assignmentID
GROUP BY DET.empname
Just add a WHERE clause if you need one.
if you want you result as a query without CTEs this should work:
select empName,
empNo,
(select employee_details.empNo, count(employee_assignment.assId)
from employee_details as t1
join employee_assignment on (t1.empno = employee_assignment.empno)
join employee_assignment_property on (employee_assignment.assId = employee_assignment_property.assId)
where employee_assignment.ptop = 'COMPLETED'
and t.empNo = t1.empNo
group by t1.empNo ) as [COMPLETED],
(select employee_details.empNo, count(employee_assignment.assId)
from employee_details as t1
join employee_assignment on (t1.empno = employee_assignment.empno)
join employee_assignment_property on (employee_assignment.assId = employee_assignment_property.assId)
where employee_assignment.ptop = 'STARTED'
and t.empNo = t1.empNo
group by t1.empNo ) as [STARTED],
from employee_details as t
If you don't want to do a dirty query composed of subqueries, you can try creating a view (if your database permits it).
What does it mean : I'll be useless in front of this. In summary, a view is a temporary table.
Hope this helps
this should work using CTEs:
Using Common Table Expressions
with numComplet()
as
(
select tbl1.empNo, count(tbl2.assId)
from tbl1
join tbl2 on (tbl1.empno = tbl2.empno)
join tbl3 on (tbl2.assId = tbl3.assId)
where tbl2.ptop = 'COMPLETED'
group by tbl1.empNo
),
with numStarted()
as
(
select tbl1.empNo, count(tbl2.assId)
from tbl1
join tbl2 on (tbl1.empno = tbl2.empno)
join tbl3 on (tbl2.assId = tbl3.assId)
where tbl2.ptop = 'STARTED'
group by tbl1.empNo
)
select *
from tbl1
join numComplet on (tbl1.empNo = numComplet.empNo)
join numStarted on (tbl1.empNo = numStarted.empNo)
I put down table names as tbl[1|2|3]

How to retrive the effective dated empid from PS_JOB table

I am new to peoplesoft. I can understand the effective date at a conceptual level, but I am still struggling with it in SQR. How do I retrieve the effective dated empid from PS_JOB table? How do I retrieve the valid empname from ps_names for the retrieved empid? Thanks in advance!
the current name - from the ps_names_vw view
you can use a similar where clause for the ps_job table.
select a.emplid,
a.name_type,
a.effdt,
a.last_name,
a.first_name,
a.middle_name,
a.name_prefix,
a.name_suffix,
a.last_name_srch,
a.first_name_srch,
a.name_display
from ps_names a
where a.effdt = (select max (b.effdt)
from ps_names b
where b.emplid = a.emplid and
b.name_type = a.name_type and
b.effdt <= to_date (to_char (sysdate, 'YYYY-MM-DD'), 'YYYY-MM-DD'));
Join names and job table with their respective effective date. here i have taken A, L, P, S employees assuming you need active employees' names only. if not , you can remove empl_status criterion. Also you need to specify the name_type in the main criterion , otherwise multiple rows may be returned for one emplid.
SELECT * FROM PS_NAMES N, PS_JOB J
WHERE N.EMPLID = J.EMPLID
AND N.EFFDT = (SELECT MAX(N1.EFFDT) FROM PS_NAMES N1
WHERE N1.EMPLID= N.EMPLID
AND N1.NAME_TYPE = N.NAME_TYPE
AND N1.EFFDT <= SYSDATE)
AND J.EFFDT = (SELECT MAX(J1.EFFDT) FROM PS_JOB J1
WHERE J1.EMPLID = J.EMPLID
AND J1.EMPL_RCD = J.EMPL_RCD
AND J1.EFFDT <= SYSDATE)
AND J.EFFSEQ = (SELECT MAX(J2.EFFSEQ) FROM PS_JOB J2
WHERE J2.EMPLID = J.EMPLID
AND J2.EMPL_RCD = J.EMPL_RCD
AND J2.EFFDT = J.EFFDT)
AND J.EMPL_STATUS IN ('A','L','P','S')
The below query will fetch you the most recent data of an employee with Emplid 'XXX' from PS_JOB
SELECT * FROM PS_JOB J
WHERE J.EMPLID = 'XXX'
AND J.EFFDT = (SELECT MAX(J1.EFFDT)
FROM PS_JOB J1
WHERE J1.EMPLID =J.EMPLID
AND J1.EMPL_RCD = J.EMPL_RCD
AND J1.EFFDT < TRUNC(SYSDATE))
AND J.EMPL_RCD = ( SELECT MAX(J2.EMPL_RCD)
FROM PS_JOB J2
WHERE J2.EMPLID = J.EMPLID
AND J2.EFFDT = J.EFFDT )
AND J.EFFSEQ = ( SELECT MAX(J3.EFFSEQ)
FROM PS_JOB J3
WHERE J3.EMPLID = J.EMPLID
AND J3.EMPL_RCD = J.EMPL_RCD
AND J3.EFFDT = J.EFFDT)
ORDER BY J.EMPLID , J.EMPL_RCD, J.EFFDT, J.EFFSEQ

distinct records with inner join in oracle joins

I am using following query to return a list of records:
Select DISTINCT A.Id Questionid,
A.Created_Date Questiondate,
Row_Number() Over ( Order By A.Created_Date Desc) Row_Id,
B.Id Answerid,
COUNT(*) OVER (partition by a.id) QCOUNT,
B.Created_Date Answerdate
From Question_Table A
Inner Join Answers_Table B
ON A.Id = B.Question_Id
AND A.Is_Active = 1
AND A.Is_Delete = 0
And B.Is_Active = 1
And B.Is_Delete = 0
And A.Category_Id = 1318221772
Answers_Table.question_id is mapped to question_table.id
Hence, for a particular question id, there can be more than one rows on answers_table.
The Output now displaying is:
QUESTIONID QUESTIONDATE ROW_ID ANSWERID QCOUNT ANSWERDATE
52776 08-DEC-12 1 31383 2 09-DEC-12
52776 08-DEC-12 2 31482 2 10-DEC-12
52719 07-DEC-12 3 31321 1 07-DEC-12
But my requirement to display output as:
QUESTIONID QUESTIONDATE ROW_ID ANSWERID QCOUNT ANSWERDATE
52776 08-DEC-12 1 31383 2 09-DEC-12
52719 07-DEC-12 3 31321 1 07-DEC-12
How can I display unique questionid (like 52776,52719) on to the output?
Depending on what you are trying to do you may be able to rewrite this with a Group By statement. However, if you want to keep your existing query, try changing this line:
Row_Number() Over (Order By A.Created_Date Desc) Row_Id,
to this:
Row_Number() Over ( partition by a.id Order By B.Created_Date ASC) Row_Id,
And then make the whole thing a subquery selecting where row_id = 1. This should just return one row per Question and only the earliest Answer for that Question.
Select * From (
Select DISTINCT A.Id Questionid,
A.Created_Date Questiondate,
Row_Number() Over ( partition by a.id Order By B.Created_Date ASC) Row_Id,
B.Id Answerid,
COUNT(*) OVER (partition by a.id) QCOUNT,
B.Created_Date Answerdate
From Question_Table A
Inner Join Answers_Table B
ON A.Id = B.Question_Id
AND A.Is_Active = 1
AND A.Is_Delete = 0
And B.Is_Active = 1
And B.Is_Delete = 0
And A.Category_Id = 1318221772
) Where ROW_ID = 1