I am further taking reference from : Apply OFFSET and LIMIT in ORACLE for complex Join Queries?.
How to find out the MIN and MAX value of rn here ?
SELECT q.*
FROM (SELECT DEPT.ID rowobjid,
DEPT.CREATOR createdby,
DEPT.CREATE_DATE createddate,
DEPT.UPDATED_BY updatedby,
DEPT.LAST_UPDATE_DATE updateddate,
DEPT.NAME name,
DEPT.STATUS status,
statusT.DESCR statusdesc,
REL.ROWID_DEPT1 rowidDEPT1,
REL.ROWID_DEPT2 rowidDEPT2,
DEPT2.DEPT_FROM_VAL parentcid,
DEPT2.NAME parentname,
ROW_NUMBER() OVER (PARTITION BY DEPT.CREATE_DATE ORDER BY DEPT.ID) AS rn
FROM TEST.DEPT_TABLE DEPT
LEFT JOIN TEST.STATUS_TABLE statusT
ON DEPT.STATUS = statusT.STATUS
LEFT JOIN TEST.C_REL_DEPT rel
ON DEPT.ID = REL.ROWID_DEPT2
LEFT JOIN TEST.DEPT_TABLE DEPT2
ON REL.ROWID_DEPT1 = DEPT2.ID) q
Min value of rn will always be 1 and for finding the max. Use max after * as follows:
SELECT q.*, max(rn) over () as max_rn, 1 as min_rn
FROM (SELECT
.......
.......
If you want max rn within inner query for each partition then you can use count analytical function as it will return total number of records within the defined partition(which is nothing but the max rn for that partition) as follows:
COUNT(1) OVER (PARTITION BY DEPT.CREATE_DATE) AS MAX_RN, 1 AS MIN_RN
Related
I have an employee table as below. As you can see that second highest salary is 200
Incase the second highest salary is missing then there will be only one row as shown at last . In this case the query should fetch only 100
I have written query as but it is not working. Please help! Thanks
select salary "SecondHighestSalary" from(
(select id,salary,rank() over(order by salary desc) rnk
from employee2)
)a
where (rnk) in coalesce(2,1)
I have also tried the following but it is fetching 2 rows but i need only 1
It sounds like you'd want something like
with ranked_emp as (
select e.*,
rank() over (order by e.sal desc) rnk,
count(*) over () cnt
from employee2 e
)
select salary "SecondHighestSalary"
from ranked_emp
where (rnk = 2 and cnt > 1)
or (rnk = 1 and cnt = 1)
Note that I'm still using rank since you're using that in your approach and you don't specify how you want to handle ties. If there are two employees with the same top salary, rank will assign both a rnk of 1 and no employee would have a rnk of 2 so the query wouldn't return any data. dense_rank would ensure that there was at least one employee with a rnk of 2 if there were employees with at least 2 different salaries. If there are two employees with the same top salary, row_number would arbitrarily assign one the rnk of 2. The query I posted isn't trying to handle those duplicate situations because you haven't outlined exactly how you'd want it to behave in each instance.
If you are in Oracle 12.2 or higher, you can try:
select distinct id,
nvl
(
nth_value(salary, 2) from first
over(partition by id
order by salary desc
range between unbounded preceding and unbounded
following),
salary
) second_max_salary
from employee2
Table 1 has duplicate entries in column A with same frequency values. I need to select one random record out of those .If the duplicate entry contain 'unknown' as a column B value ( like in record "d") select one from other rows . I need a select statement which satisfy the above . Thanks .
These conditions can be prioritized using a case expression in order by with a function like row_number.
select A,B,frequency,timekey
from (select t.*
,row_number() over(partition by A order by cast((B = 'unknown') as int), B) as rnum
from tbl t
) t
where rnum = 1
Here for each group of A rows, we prioritize rows other than B = 'unknown' first, and then in the order of B values.
Use row_number analytic function. If you want to select not unknown record first, then use the query below:
select A, B, Frequency, timekey
from
(select
A, B, Frequency, timekey,
row_number() over(partition by A,Frequency order by case when B='unknown' then 1 else 0 end) rn
)s where rn=1
And if you want to select unknown if they exist, use this row_number in the query above:
row_number() over(partition by A,Frequency order by case when B='unknown' then 0 else 1 end) rn
I want to populate temp2 with max tot_duration and count from temp1. I do it using the following code:
insert into analytics_db.charith_prepaid_bcell_temp2
(charged_party,cell_id,tot_duration,tband_count)
select A.*
FROM analytics_db.charith_prepaid_bcell_temp1 A,
(SELECT A.charged_party,B.B,MAX(A.tot_duration) C-- MAX COUNT FOR MAX TIMA BAND CELL
FROM analytics_db.charith_prepaid_bcell_temp1 A,
(SELECT charged_party,MAX(tband_count) B ---- MAX TIME BAND COUNT
FROM analytics_db.charith_prepaid_bcell_temp1
WHERE NVL(tot_duration,0) >0
GROUP BY charged_party) B
WHERE NVL(tot_duration,0) >0 AND A.charged_party = B.charged_party AND A.tband_count = B.B
GROUP BY A.charged_party,B.B) C
WHERE A.charged_party = C.charged_party AND A.tot_duration= C.C AND A.tband_count = C.B
But there are duplicate entries in the temp2 where there are different cell id with same tot_duration and tband_count for the same charged_party. How can I fix the code to only get the entry where there is only one entry with the maximum cell_id?
Thank you
This can be done with ranking functions like row_number.
select charged_party,cell_id,tot_duration,tband_count
from (select t.*
,row_number() over(partition by tot_duration,tband_count order by cell_id desc) as rnum
from tbl t
) t
where rnum = 1
I looked at the other questions related to this but it did not work. I even played around with Dense_Rank and still couldn't get the right answer.
Using the Oracle Student Scheme Data. I am trying to find the highest 3 grades for each section based on two tables ( NOT the top 3 rows for each sections. )
This is based off the Student and the Grade table from the Student Scheme
I am using the Oracle Developer 10 and it does not look like it takes the LIMIT function. Cause it gives me the error
missing right parenthesis
select
g.SECTION_ID,g.NUMERIC_GRADE, s.First_Name,s.Last_Name
from GRADE g Join Student s
On g.student_ID = s.student_ID
and Grade_Type_Code='MT'
Where numeric_grade in(Select distinct numeric_grade
from grade
order by numeric_grade desc limit 3);
You can use ROWNUM in Oracle:
SELECT g.SECTION_ID,
g.NUMERIC_GRADE,
s.First_Name,
s.Last_Name
FROM grade g
JOIN Student s
ON g.student_ID = s.student_ID
AND Grade_Type_Code='MT'
WHERE numeric_grade in (SELECT numeric_grade
FROM (SELECT DISTINCT numeric_grade
FROM grade
ORDER BY numeric_grade desc)
WHERE ROWNUM <=3);
Solution with dense_rank:
select section_id, numeric_grade, first_name, last_name
from (
select g.section_id, g.numeric_grade, s.First_Name,s.Last_Name,
dense_rank() over (partition by g.section_id
order by g.numeric_grade desc) rnk
from GRADE g
join Student s on g.student_ID = s.student_ID
and Grade_Type_Code='MT' )
where rnk < 4
order by section_id, numeric_grade desc
SQLFiddle demo
For Oracle,
I have 2 tables; first is Store and another is Book whereas they are connected by store ID (PK FK).
I would like to lists the name of the store which has the highest numbers of books.
However, the result showed every store in orders but I just want the highest.
SELECT STORE.STORE_NAME
FROM STORE, BOOK
WHERE STORE.STORE_ID=BOOK.BOOK_STOREID
GROUP BY STORE.STORE_NAME
ORDER BY COUNT(BOOK.BOOK_STOREID) DESC;
the result is
Store:
D
E
F
B
A
C
It should be only 'D'. What should I do? Thank you.
Try
SELECT STORE_NAME
FROM
(SELECT STORE.STORE_NAME
FROM STORE, BOOK
WHERE STORE.STORE_ID=BOOK.BOOK_STOREID
GROUP BY STORE.STORE_NAME
ORDER BY COUNT(BOOK.BOOK_STOREID) DESC)
WHERE rownum = 1
Here is a sqlfiddle demo
BTW, you can also use row_number() function
select STORE_NAME
from
(SELECT STORE.STORE_NAME,
row_number() over( order by COUNT(BOOK.BOOK_STOREID)desc) rn
FROM STORE join BOOK on STORE.STORE_ID=BOOK.BOOK_STOREID
group by STORE.STORE_NAME)
where rn = 1;
UPDATE If you want to see all stores which have the max number of books you can use rank instead of row_number:
select STORE_NAME
from
(SELECT STORE.STORE_NAME,
rank() over( order by COUNT(BOOK.BOOK_STOREID)desc) rn
FROM STORE join BOOK on STORE.STORE_ID=BOOK.BOOK_STOREID
group by STORE.STORE_NAME)
where rn = 1;
Just for fun, here's another formulation:
with store_counts as (
select store_name,
count(*) books
from store join book on store_id=book_storeid
group by store_name)
select *
from store_counts
where books = (
select max(books)
from store_counts)