This question already has answers here:
Fetch the rows which have the Max value for a column for each distinct value of another column
(35 answers)
Closed 6 months ago.
I have a table save sending & receiving process as example
id
sender
receiver
1
A
A
2
A
B
3
A
C
4
B
D
5
D
B
6
B
D
But i don't know how to write oracle query to select the latest with unique receiver. Expected result as:
id
sender
receiver
1
A
A
3
A
C
5
D
B
6
B
D
Any ideas on how I can accomplish the result i'm after?
We can use ROW_NUMBER() here:
WITH cte AS (
SELECT t.*, ROW_NUMBER() OVER (PARTITION BY receiver ORDER BY id DESC) rn
FROM yourTable t
)
SELECT id, sender, receiver
FROM cte
WHERE rn = 1
ORDER BY id;
Related
I have a one to many relationship
shipment
id
bill
1
2222
2
4255
shipment_status
id
status
1
created
1
Shipped
2
created
2
Shipped
2
Delivered
3
created
3
Shipped
4
Created
4
Shipped
4
Delivered
5
Created
What I want to get
Results
count
status
2
Shipped
2
Delivered
1
Created
What I've done :
SELECT a.status,
b.total_status
FROM hipmenthistories a
INNER JOIN (
SELECT status,
MAX(created_at) last_status,
COUNT(*) total_status
FROM shipmenthistories
GROUP BY status
) b ON a.status = b.status`
Actual data in the db fiddle
Use ROW_NUMBER() and order the results by shipment and most recent status date. Then filter on the most recent status row:
See also db<>fiddle
WITH CTE AS (
SELECT status
, shipment_id
, ROW_NUMBER() OVER (PARTITION BY shipment_id ORDER BY created_at DESC, id DESC) AS rowNum
FROM shipmenthistories
)
SELECT status, COUNT(shipment_id) numOfShipments
FROM CTE
WHERE RowNum = 1
GROUP BY status;
This question already has answers here:
How to use Oracle ORDER BY and ROWNUM correctly?
(5 answers)
Closed 4 years ago.
I have two tables X and Y.
when I run below query for table X
select * from
( select rownum as rn, A.* from X as A order by A.IDdesc) where rn between 0
and 1000000;
I get result as
rn Id name
1 1 xxx
2 2 yyy
3 4 zzz
but for Y table when same query is executed I get result as
select * from
( select rownum as rn, A.* from Y as A order by A.IDdesc) where rn between 0
and 1000000;
rn Id name
5 1 xxx
7 2 yyy
10 4 zzz
rn in Y table is getting some random numbers. Not able to understand this behavior. ny help would be appreciated.
The ROWNUM pseudo-column is added to the selected columns in the order Oracle retrieves the rows and then the ORDER BY clause is applied. What you appear to want is to order the rows first and then generate the ROWNUM against this ordering but that is not what your query will do.
For table X, it happens that Oracle retrieves the rows in the same order as the id column. However, for table Y, the rows are not retrieved in the same order as the id column so the ROWNUM is in the order the rows were retrieved and then a different ordering is applied so the ROWNUM values appear shuffled.
What you should do is to apply the ORDER BY before generating the ROWNUM pseudo-column so they are in-sync:
SELECT *
FROM (
SELECT rownum as rn,
A.*
FROM (
SELECT *
FROM X
ORDER BY ID desc
) A
)
WHERE rn BETWEEN 0 AND 1000000;
I have to fetch the first and last row of the table in Toad.
I have used the following query
select * from grade_master where rownum=(select max(rownum) from grade_master)
select * from grade_master where rownum=1
The second query works to fetch the first row. but the first not working. Anyone please help me.
Thanks in advance
Such request makes sense if you specify sort order of the results - there are no such things in database as "first" and "last" rows if sort order is not specified.
SQL> with t as (
2 select 'X' a, 1 b from dual union all
3 select 'C' , 2 from dual union all
4 select 'A' a, 3 b from dual
5 )
6 select a, b, decode(rn, 1, 'First','Last')
7 from (
8 select a, b, row_number() over(order by a) rn,
9 count(*) over() cn
10 from t
11 )
12 where rn in (1, cn)
13 order by rn
14 /
A B DECOD
- ---------- -----
A 3 First
X 1 Last
In oracle the data is not ordered until you specify the order in you sql statement.
So when you do:
select * from grade_master
oracle will give the rows in anyway it want wants.
OTOH if you do
select * from grade_master order by id desc
Then oracle will give the rows back ordered by id descending.
So to get the last row you could do this:
select *
from (select * from grade_master order by id desc)
where rownum = 1
The rownum is determined BEFORE the "order by" clause is assessed, so what this query is doing is ordering the rows descending (the inside query) and then giving this ordered set to the outer query. The outer gets the first row of the set then returns it.
This question already has answers here:
Oracle aggregate for joining strings with comma, and about writing custom aggregates
(3 answers)
Closed 8 years ago.
Please help me to do the following in Oracle.
I have something like column called id , and I need in concatenation
Id
1
2
3
4
5
6
8
9
9
I need a query which returns 1,2,3,4,5,6,7,8,9,9
How can I do this?
Try this,
WITH t(ID) AS
(
SELECT 1 FROM dual
UNION
SELECT 2 FROM dual
UNION
SELECT 3 FROM dual
UNION
SELECT 4 FROM dual
)
SELECT LISTAGG(ID, ',') WITHIN GROUP (ORDER BY ID)
FROM t;
try
select ltrim(max(sys_connect_by_path(id, ',')), ',')
from (select id, rownum t
from yourtable t)
connect by prior t = t - 1
start with t = 1;
I have this query that takes about 5 minutes to return a result set and I can't figure out a better way to do it. The table in question has about 15 or 20 million rows at all times and its schema can be summarized as
create table conversation(
id raw, -- GUID
vendor varchar,
snumber number
rcvdate date
)
where we store messages sent from or to a vendor, each message has a sequence number shared by all the conversation (set of related messages). The problem comes because the vendor can have a parent and the message can have the parent's code (we can assume we know both the code of the vendor and their parent's code at the time of the query). Suppose that A and B are 2 vendors with a common parent P, the table might look like
Vendor snumber date
------------------------------
A 1 01-JAN-2012
P 1 02-JAN-2012
A 1 02-JAN-2012
A 2 03-JAN-2012
P 2 03-JAN-2012
B 3 03-JAN-2012
P 3 04-JAN-2012
A 2 04-JAN-2012
We need to query the last N messages from/to A and get the messages with vendor=A OR (vendor=P and another record with vendor=A and same snumber), that is:
Vendor snumber date
------------------------------
A 1 01-JAN-2012
P 1 02-JAN-2012
A 1 02-JAN-2012
A 2 03-JAN-2012
P 2 03-JAN-2012
A 2 04-JAN-2012
What I did was to store the conversations to/from A in a temporary table T(id, snumber) and then return
select * from (
select * from conversations c
where
exists (select id from T where T.id = C.id) or
( c.vendor=l_parent and exists (select snumber from T where T.snumber=c.snumber )
) where rownum <= l_N
those 2 subqueries are killing the performance. The conversations table has indexes in all the columns I included in this example.
I'm thinking the has to a be a clever way to group this information without having to use temporary tables or subqueries but I can't think of one. Any help will be appreciated.
it sounds like you want something like this:
SQL> select vendor, snumber, rcvdate
2 from (select vendor, snumber, rcvdate,
3 max(case when vendor = 'A' then 'Y' end) over (partition by snumber) has_vendor
4 from conversation
5 where vendor in ( 'A', 'P' )
6 order by rcvdate desc)
7 where has_vendor = 'Y'
8 and rownum <= 100
9 order by rcvdate;
V SNUMBER RCVDATE
- ---------- --------------------
A 1 01-jan-2012 00:00:00
P 1 02-jan-2012 00:00:00
A 1 02-jan-2012 00:00:00
P 2 03-jan-2012 00:00:00
A 2 03-jan-2012 00:00:00
A 2 04-jan-2012 00:00:00
i.e.
max(case when vendor = 'A' then 'Y' end) over (partition by snumber) has_vendor
says if there's an 'A' vendor in that snumber, then you want to return that for the "P"arent vendor otherwise not.