获取每个分组依据 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 订购。但是多次有相同的日期,所以它也不会解决你的问题。

这是一个不使用分析函数的通用查询。

SQLFiddle Demo

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