This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Oracle SQL - How to Retrieve highest 5 values of a column
i have a table abc, where i have following columns
act_id,cust_id,lastUpdatedDate,custActivity. Where act_id is primary key .
lastUpdatedDate store last activity done for this customer.
i am trying to get latest 10 rows for given custid based on lastUpdatedDate.
How can i achieve it.
-vivek
You can use ROWNUM in Oracle.. Click Here for Documentation
select *
from
( select *
from your_table
where cust_id=<given cust_id>
order by lastUpdatedDate desc )
where ROWNUM <= 10;
Oracle supports ROW_NUMBER() and window function. Try the following,
SELECT act_id, cust_id, lastUpdatedDate, custActivity
FROM
(
SELECT act_id, cust_id, lastUpdatedDate, custActivity,
ROW_NUMBER() OVER (PARTITION BY cust_id ORDER BY lastUpdatedDate DESC) rn
FROM tableNAME
) x
WHERE rn <= 10
Hope this may helpful to you-
select act_id,cust_id,lastUpdatedDate,custActivity
from (
select act_id,cust_id,lastUpdatedDate,custActivity, row_number() over (order by lastUpdatedDate) r
from abc
where act_id=<cust_id>
)
where r between 1 and 10;
Related
This question already has answers here:
Get top 1 row of each group
(19 answers)
Closed last month.
I have duplicates like these in a table:
I can select the duplicates, but I need to select only the ones marked in yellow, aka: the oldest of the duplicates. How could I filter those?
You can use ROW_NUMBER() window function to identify the oldest record, and then just select that:
SELECT *
FROM
(
SELECT yt.*, ROW_NUMBER() OVER (PARTITION BY REFERENCE ORDER BY CREATION DATE ASC) as rn
FROM yt
)
WHERE rn = 1;
This question already has answers here:
Get top 1 row of each group
(19 answers)
Closed 10 months ago.
I have such a situation. I need to make a code work so that it selects only one PVISBN (Item Number) based on PVLICP (license plate) (I need to get only the first row from 2 that I am getting back).
TableSeven AS (
SELECT PVISBN, PVWHS, PVLICP, PVRZNE, PVRLOC, PVAZNE, PVALOC, PVLPRG,
ROW_NUMBER() OVER (PARTITION BY PVISBN, PVRZNE ORDER BY PVLICP --, PVRLOC, PVAZNE, PVALOC, PVLPRG
ASC) AS rn
FROM [REPIT].[LEVYDTA].[WHSPDVT]
WHERE PVSPDT BETWEEN #Last2WeekDATE AND #LWDate
--AND PVISBN='0164556221'
) ,
TableTwelve AS (
SELECT PVISBN, PVWHS, PVLICP, PVRZNE, PVRLOC, PVAZNE, PVALOC, PVLPRG, rn
FROM TableSeven
WHERE rn = 1
),
I keep getting 2 rows and should get only the 1st one
If someone may have an idea, I will appreciate.
Assuming "Oldest" and "Lowest" is the same, you can use aggregation:
SELECT PVISBN, MIN(PVLICP) as PVLICP
FROM yourtable
GROUP BY PVISBN;
To your comment, if you are wanting all columns in the output, then consider window functions (also called Analytics Functions or Ordered Analytics Functions) to help identify the min() for a group/window (PVISBN in this case) and then filter:
SELECT *
FROM
(
SELECT yourtable.*, ROW_NUMBER() OVER (PARTITION BY PVISBN ORDER BY PVLICP ASC) as rn
FROM yourtable
) dt
WHERE rn = 1;
That will generate a row_number, starting at 1 for each row for each distinct PVISBN (you can run just the subquery to see how that looks). Then we just filter for rn of 1, which will be the record for that PVISBN with the lowest PVLICP.
I think this would be helpful for you
SELECT PVISBN, PVWHS, MIN(PVLICP) as PVLICP , ------------ FROM tablename WHERE PVLICP IS NOT NULL or PVLICP <> '' group by PVISBN;
This question already has answers here:
How do I do top 1 in Oracle? [duplicate]
(9 answers)
How do I limit the number of rows returned by an Oracle query after ordering?
(14 answers)
Oracle SELECT TOP 10 records [duplicate]
(6 answers)
How to use Oracle ORDER BY and ROWNUM correctly?
(5 answers)
Closed 5 years ago.
There is a clear answer how to select top 1:
select * from table_name where rownum = 1
and how to order by date in descending order:
select * from table_name order by trans_date desc
but they does not work togeather (rownum is not generated according to trans_date):
... where rownum = 1 order by trans_date desc
The question is how to select top 1 also ordered by date?
... where rownum = 1 order by trans_date desc
This selects one record arbitrarily chosen (where rownum = 1) and then sorts this one record (order by trans_date desc).
As shown by Ivan you can use a subquery where you order the records and then keep the first record with where rownum = 1in the outer query. This, however, is extremely Oracle-specific and violates the SQL standard where a subquery result is considered unordered (i.e. the order by clause can be ignored by the DBMS).
So better go with the standard solution. As of Oracle 12c:
select *
from table_name
order by trans_date desc
fetch first 1 row only;
In older versions:
select *
from
(
select t.*, row_number() over (order by trans_date desc) as rn
from table_name t
)
where rn = 1;
Modern Oracle versions have FETCH FIRST:
select * from table_name order by trans_date desc
fetch first 1 row only
There should be subquery so the combination rownum & order could work:
select * from (select * from table_name order by trans_date desc) AS tb where rownum = 1
You can use window functions for that:
select t.*
from (
select *,
min(trans_date) over () as min_date,
max(trans_date) over () as max_date
from the_table
) t
where trans_date = min_date
or trans_date = max_date;
Another option would be to join on the derived table
select t1.*
from the_table
join (
select min(trans_date) over () as min_date,
max(trans_date) over () as max_date
from the_table
) t2 on t1.trans_date = t2.min_date
or t1.trans_date = t2.max_date;
Not sure which one would be faster, you need to check the execution plan
This question already has answers here:
How do I limit the number of rows returned by an Oracle query after ordering?
(14 answers)
Closed 5 years ago.
I have a question regarding a SQl query in Oracle where IO need to select rthe row with the most recent date and time where date and time are inserted into two separate columns.
Table TransactionRecords
CustomerID TransactionDate TransactionTime
-------------------------------------------------------
0206016 17-APR-17 15:29:34
0213570 17-APR-17 15:29:32
0211384 17-APR-17 13:29:34
0487674 16-APR-17 14:29:30
0487759 15-APR-17 13:29:32
0487213 12-APR-17 13:29:32
0191022 11-APR-17 15:29:33
1141158 29-OCT-16 01:25:51
I am expecting my query to rerturn the most recent transaction which should be :
CustomerID TransactionDate TransactionTime
---------------------------------------------------
0206016 17-APR-17 15:29:34
When I am running the following query :
select * from TransactionRecords tst
where tst.TransactionDate in (select max(TransactionDate) from
TransactionRecords)
I am getting all the transactions that happened on the most recent date.
Can someone please give me any suggestions?
In Oracle 12c you can do:
SELECT *
FROM your_table
ORDER BY TransactionDate DESC, TransactionTime DESC
FETCH FIRST 1 ROWS ONLY;
In lower versions, you can use the ROWNUM pseudo-column:
SELECT *
FROM (
SELECT *
FROM your_table
ORDER BY TransactionDate DESC, TransactionTime DESC
)
WHERE ROWNUM = 1;
Use row_number(). I've used a CTE for visibility, but subquery will work too
with CTE as
(
select t1.*,
row_number() over(order by TransactionDate desc, TransactionTime desc) as rn
from MyTable t1
)
select CTE.*
from CTE
where rn = 1
select * from TransactionRecords tst
ORDER BY tst.TransactionDate||tst.TransactionTime DESC
Such SQL query:
SELECT ROW_NUMBER() OVER (PARTITION BY ID, YEAR order by ID ), ID, YEAR
from table t
give me following query set:
1 1000415591 2012
1 1000415591 2013
2 1000415591 2013
1 1000415591 2014
2 1000415591 2014
How could I update records with ROW_NUMBER() equals to 2? Other fields of this records is identically (select distinct from table where id = 1000415591 gives 3 records when there are 5 without distinct keyword), so I can depend only on ROW_NUMBER() value.
I need solution for Oracle, because I saw something similar for SQL-Server but it won't work with Oracle.
You could use a MERGE statement which is quite verbose and easy to understand.
For example,
MERGE INTO t s
USING
(SELECT ROW_NUMBER() OVER (PARTITION BY ID, YEAR order by ID ) RN,
ID,
YEAR
FROM TABLE t
) u ON (s.id = u.id)
WHEN MATCHED THEN
UPDATE SET YEAR = some_value WHERE u.RN = 2)
/
Note You cannot merge the same column which is used to join in the ON clause.
Try to use ROWID field:
UPDATE T
SET t.year = t.year*1000
WHERE (rowid,2) in (SELECT rowid,
ROW_NUMBER()
OVER (PARTITION BY ID, t.YEAR order by ID )
FROM T)
SQLFiddle demo
If you need to delete range of ROWNUMBERS then :
UPDATE T
SET t.year = t.year*1000
WHERE rowid in ( SELECT rowid FROM
(
SELECT rowid,
ROW_NUMBER()
OVER (PARTITION BY ID, t.YEAR order by ID ) as RN
FROM T
) T2 WHERE RN >=2 AND RN <=10
)
SQLFiddle demo
This is not the update statement but this is how to get the 2 rows you wanted to update:
SELECT *
FROM (
SELECT ROW_NUMBER() OVER (PARTITION BY ID, YEAR order by ID ) as rn, ID, YEAR
from t )
where rn = 2
SQLFIDDLE
When I've posted thq question, I've found that this could be wrong approach. I could modify table and add new fields. So better solution to create one more field IDENTITY and update it with numbers from the new sequence from 1 to total row numbers. Then I could update fields based on this IDENTIY field.
I'll keep this question opened if someone come up with solution based on ROW_NUMBER() analytic function.
update TABLE set NEW_ID = TABLE_SEQ.nextval
where IDENTITY in (
select IDENTITY from (
select row_number() over(PARTITION BY ID, YEAR order by ID) as row_num, t.ID, t."YEAR", t.IDENTITY
from TABLE t
) where row_num > 1
)