问题
Hello I'm having trouble with getting the Top 1 row using the below query. its in oracle, plsql.
SELECT per.person_no,
perbus.person_no,
perbus.edit_dt,
perbus.org_name,
perbus.FIRST_NAME
FROM users.persons per
LEFT OUTER JOIN (
SELECT ASSOC.edit_dt,PER_CONTACTS.PERSON_NO,
PER_CONTACTS.PERSON_ID AS PER_ID,
PER.EXTERNAL_PERSON_ID AS EXT_PER_ID,
PER_CONTACTS.LNAME||', '||PER_CONTACTS.FNAME AS NAME,
PER_CONTACTS.FNAME AS FIRST_NAME,
PER_CONTACTS.MNAME AS MIDDLE_NAME,
PER_CONTACTS.LNAME AS LAST_NAME,
ORG.ORG_NAME AS ORG_NAME,
T_ORG.ORG_ID AS ORG_ID,
T_ORG.ORG_DISPLAY_ID AS EXT_ORG_ID,
rownum AS rn
FROM USERS.PER_CONTACTS PER_CONTACTS
LEFT OUTER JOIN USERS.PERSONS PER ON PER.PERSON_ID = PER_CONTACTS.PERSON_ID
LEFT OUTER JOIN USERS.ASSOC ASSOC ON ASSOC.PERSON_ID = PER.PERSON_ID
LEFT OUTER JOIN USERS.T_ORG T_ORG ON T_ORG.T_ORG_ID = ASSOC.T_ORG_ID
LEFT OUTER JOIN USERS.ORG ORG ON ORG.ORG_ID = T_ORG.ORG_ID
WHERE PER_CONTACTS.CONTACT_ROLE_LOV = 'EMPLOYEE' AND PER_CONTACTS.PERSON_NO IN (SELECT PERSON_NO FROM USERS.QA_APPROVED)
ORDER BY ASSOC.edit_dt DESC
)
perbus ON perbus.PERSON_NO = PER.PERSON_NO
WHERE PER.PERSON_NO IN (SELECT PERSON_NO FROM USERS.QA_APPROVED)
I'm new to oracle and in the above query i'm getting duplicates because of the data - and i need to get the first record based on the Assoc.edit_dt.
I'm able to order the record by Assoc.edit_dt, but when i use a clause like where row_num = 1 inside the Join, my output query is null for all perbus table fields.
Please advise.
回答1:
Try this
If you want to return TOP 1 row by PERSON_NO then
replace
rownum as rn
with
ROW_NUMBER() OVER (PARTITION BY PER_CONTACTS.PERSON_NO
ORDER BY ASSOC.edit_dt DESC) RN
If you want to return TOP 1 overall then
replace
rownum as rn
with
ROW_NUMBER() OVER (ORDER BY ASSOC.edit_dt DESC) RN
Finally in your outer where clause just do RN = 1 to pick top 1 row
WHERE PER.PERSON_NO IN (select PERSON_NO from USERS.QA_APPROVED) AND RN = 1
回答2:
Here using analytical function will definitely resolve your issue.Based on the person_id and Assoc_edt_dt we can pull out only one record having max/min row. Below is snippet which you can try. Hope it helps
SELECT per.person_no,
perbus.person_no,
perbus.edit_dt,
perbus.org_name,
perbus.FIRST_NAME
FROM users.persons per
LEFT OUTER JOIN
(SELECT ASSOC.edit_dt,
PER_CONTACTS.PERSON_NO,
PER_CONTACTS.PERSON_ID AS PER_ID,
PER.EXTERNAL_PERSON_ID AS EXT_PER_ID,
PER_CONTACTS.LNAME
||', '
||PER_CONTACTS.FNAME AS NAME,
PER_CONTACTS.FNAME AS FIRST_NAME,
PER_CONTACTS.MNAME AS MIDDLE_NAME,
PER_CONTACTS.LNAME AS LAST_NAME,
ORG.ORG_NAME AS ORG_NAME,
T_ORG.ORG_ID AS ORG_ID,
T_ORG.ORG_DISPLAY_ID AS EXT_ORG_ID,
ROW_NUMBER() OVER(PARTITION BY PER_CONTACTS.PERSON_ID ORDER BY ASSOC.edit_dt DESC) rn
FROM USERS.PER_CONTACTS PER_CONTACTS
LEFT OUTER JOIN USERS.PERSONS PER
ON PER.PERSON_ID = PER_CONTACTS.PERSON_ID
LEFT OUTER JOIN USERS.ASSOC ASSOC
ON ASSOC.PERSON_ID = PER.PERSON_ID
LEFT OUTER JOIN USERS.T_ORG T_ORG
ON T_ORG.T_ORG_ID = ASSOC.T_ORG_ID
LEFT OUTER JOIN USERS.ORG ORG
ON ORG.ORG_ID = T_ORG.ORG_ID
WHERE PER_CONTACTS.CONTACT_ROLE_LOV = 'EMPLOYEE'
AND PER_CONTACTS.PERSON_NO IN
(SELECT PERSON_NO FROM USERS.QA_APPROVED
)
ORDER BY ASSOC.edit_dt DESC
) perbus ON perbus.PERSON_NO = PER.PERSON_NO
WHERE PER.PERSON_NO IN
(SELECT PERSON_NO FROM USERS.QA_APPROVED
)
AND perbus.rn = 1;
回答3:
To fetch just "few" records from a dataset you can user "rownum" - here is an example:
select * from user_tables where rownum < 4
Another example (select first 2 rows based on "table_name):
select * from (select * from user_tables order by table_name) where rownum<3
Note: do not use equality (=) sign you must use (<) for this.
回答4:
You can use Result offset and fetch first clauses (only works on 12c)
just add
FETCH FIRST ROW ONLY;
after the order by clause
For more info. read this
Hope this helps =)
EDIT:
SELECT per.person_no,
perbus.person_no,
perbus.edit_dt,
perbus.org_name,
perbus.FIRST_NAME
FROM users.persons per
LEFT OUTER JOIN (
SELECT ASSOC.edit_dt AS EDIT_DT,PER_CONTACTS.PERSON_NO,
PER_CONTACTS.PERSON_ID AS PER_ID,
PER.EXTERNAL_PERSON_ID AS EXT_PER_ID,
PER_CONTACTS.LNAME||', '||PER_CONTACTS.FNAME AS NAME,
PER_CONTACTS.FNAME AS FIRST_NAME,
PER_CONTACTS.MNAME AS MIDDLE_NAME,
PER_CONTACTS.LNAME AS LAST_NAME,
ORG.ORG_NAME AS ORG_NAME,
T_ORG.ORG_ID AS ORG_ID,
T_ORG.ORG_DISPLAY_ID AS EXT_ORG_ID,
rownum AS rn
FROM USERS.PER_CONTACTS PER_CONTACTS
LEFT OUTER JOIN USERS.PERSONS PER ON PER.PERSON_ID = PER_CONTACTS.PERSON_ID
LEFT OUTER JOIN USERS.ASSOC ASSOC ON ASSOC.PERSON_ID = PER.PERSON_ID
LEFT OUTER JOIN USERS.T_ORG T_ORG ON T_ORG.T_ORG_ID = ASSOC.T_ORG_ID
LEFT OUTER JOIN USERS.ORG ORG ON ORG.ORG_ID = T_ORG.ORG_ID
WHERE PER_CONTACTS.CONTACT_ROLE_LOV = 'EMPLOYEE' AND PER_CONTACTS.PERSON_NO IN (SELECT PERSON_NO FROM USERS.QA_APPROVED)
--ORDER BY ASSOC.edit_dt DESC
)
perbus ON perbus.PERSON_NO = PER.PERSON_NO
WHERE PER.PERSON_NO IN (SELECT PERSON_NO FROM USERS.QA_APPROVED)
ORDER BY perbus.edit_dt DESC
FETCH FIRST ROW ONLY;
FYI, you gave all the columns their aliases except for one and that is assoc.edit_dt but you are calling it in the main query as if it has an alias.So i took the previlige to add the alias for assoc.edit_dt
来源:https://stackoverflow.com/questions/34168550/get-only-top-row-from-sql-query