Reputation: 1334
I have the following table:
CREATE TABLE orders (
id INT PRIMARY KEY IDENTITY,
oDate DATE NOT NULL,
oName VARCHAR(32) NOT NULL,
oItem INT,
oQty INT
-- ...
);
INSERT INTO orders
VALUES
(1, '2016-01-01', 'A', 1, 2),
(2, '2016-01-01', 'A', 2, 1),
(3, '2016-01-01', 'B', 1, 3),
(4, '2016-01-02', 'B', 1, 2),
(5, '2016-01-02', 'C', 1, 2),
(6, '2016-01-03', 'B', 2, 1),
(7, '2016-01-03', 'B', 1, 4),
(8, '2016-01-04', 'A', 1, 3)
;
I want to get the most recent rows (of which there might be multiple) for each name. For the sample data, the results should be:
id | oDate | oName | oItem | oQty | ... |
---|---|---|---|---|---|
5 | 2016-01-02 | C | 1 | 2 | |
6 | 2016-01-03 | B | 2 | 1 | |
7 | 2016-01-03 | B | 1 | 4 | |
8 | 2016-01-04 | A | 1 | 3 |
The query might be something like:
SELECT oDate, oName, oItem, oQty, ...
FROM orders
WHERE oDate = ???
GROUP BY oName
ORDER BY oDate, id
Besides missing the expression (represented by ???
) to calculate the desired values for oDate
, this statement is invalid as it selects columns that are neither grouped nor aggregates.
Does anyone know how to do get this result?
Upvotes: 7
Views: 15932
Reputation: 311308
The rank
window clause allows you to, well, rank rows according to some partitioning, and then you could just select the top ones:
SELECT oDate, oName, oItem, oQty, oRemarks
FROM (SELECT oDate, oName, oItem, oQty, oRemarks,
RANK() OVER (PARTITION BY oName ORDER BY oDate DESC) AS rk
FROM my_table) t
WHERE rk = 1
Upvotes: 14
Reputation: 8093
This is a generic query without using analytical function.
SELECT a.*
FROM table1 a
INNER JOIN
(SELECT max(odate) modate,
oname,
oItem
FROM table1
GROUP BY oName,
oItem
)
b ON a.oname=b.oname
AND a.oitem=b.oitem
AND a.odate=b.modate
Upvotes: 3
Reputation: 16958
I think you need a query like this:
SELECT *
FROM (SELECT *,
ROW_NUMBER() OVER (PARTITION BY oName ORDER BY oDate DESC) seq
FROM yourTable) t
WHERE (seq <= 2)
ORDER BY oDate;
Upvotes: 2
Reputation: 9053
You have to use ROW_NUMBER
in following:
select oDate, oName, oItem, oQty, oRemarks
from (
select *, row_number() over(partition by oName, oItem order by oDate desc) rn
from #t
)x
where rn = 1
order by oDate
OUTPUT
oDate oName oItem oQty oRemarks
2016-01-01 A 001 2
2016-01-01 A 002 1 test
2016-01-02 C 001 2
2016-01-03 B 001 4
2016-01-03 B 002 1
Upvotes: 0
Reputation: 1148
Add a primary key
suppose id
field to the table and make it auto increment,. Then order by id
you will get it. It is the traditional way. By using your table you can only order by oDate
. But is is having same date multiple times, so it also won't solve your problem.
Upvotes: 2