获取每个分组依据 SQL 的最新记录
Get the latest records per Group By SQL
我有以下 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)
;
我想获取每个名称的最新行(其中可能有多个行)。对于示例数据,结果应为:
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
查询可能类似于:
SELECT oDate, oName, oItem, oQty, ...
FROM orders
WHERE oDate = ???
GROUP BY oName
ORDER BY oDate, id
除了缺少用于计算 oDate
所需值的表达式(由 ???
表示)之外,此语句无效,因为它选择了既未分组也未聚合的列。
有谁知道如何得到这个结果?
我认为您需要这样的查询:
SELECT *
FROM (SELECT *,
ROW_NUMBER() OVER (PARTITION BY oName ORDER BY oDate DESC) seq
FROM yourTable) t
WHERE (seq <= 2)
ORDER BY oDate;
你必须在下面使用 ROW_NUMBER
:
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
输出
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
rank
window 子句允许您根据某些分区对行进行排名,然后您可以 select 最上面的:
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
在 table 中添加一个 primary key
假设 id
字段并使其自动递增。然后通过 id
订购,您将获得它。这是传统的方式。通过使用您的 table,您只能按 oDate
订购。但是多次有相同的日期,所以它也不会解决你的问题。
这是一个不使用分析函数的通用查询。
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
我有以下 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)
;
我想获取每个名称的最新行(其中可能有多个行)。对于示例数据,结果应为:
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 |
查询可能类似于:
SELECT oDate, oName, oItem, oQty, ...
FROM orders
WHERE oDate = ???
GROUP BY oName
ORDER BY oDate, id
除了缺少用于计算 oDate
所需值的表达式(由 ???
表示)之外,此语句无效,因为它选择了既未分组也未聚合的列。
有谁知道如何得到这个结果?
我认为您需要这样的查询:
SELECT *
FROM (SELECT *,
ROW_NUMBER() OVER (PARTITION BY oName ORDER BY oDate DESC) seq
FROM yourTable) t
WHERE (seq <= 2)
ORDER BY oDate;
你必须在下面使用 ROW_NUMBER
:
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
输出
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
rank
window 子句允许您根据某些分区对行进行排名,然后您可以 select 最上面的:
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
在 table 中添加一个 primary key
假设 id
字段并使其自动递增。然后通过 id
订购,您将获得它。这是传统的方式。通过使用您的 table,您只能按 oDate
订购。但是多次有相同的日期,所以它也不会解决你的问题。
这是一个不使用分析函数的通用查询。
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