SQL从每个组中提取1个MAX

时间:2018-07-09 12:25:48

标签: sql sql-server

我们正在使用MS-SQL Server 2016。 从与此类似的表中(尽管已简化):

CREATE TABLE import_tbl 
    (
     id int IDENTITY(1,1) NOT NULL,
     key_date datetime2, 
     key_number int,
     other_data char(3),
     units int
    );

INSERT INTO import_tbl
(key_number, key_date, other_data, units)
VALUES
(1000000, '2014-03-31 19:10:17.110', 'AAA', 300),
(1000000, '2014-03-31 19:10:17.110', 'BBB', 200),
(1000000, '2014-02-17 14:58:42.523', 'CCC', 100),
(1000000, '2014-02-17 13:43:40.570', 'DDD', 99),
(2000000, '2014-03-31 19:04:18.157', 'AAA', 100),
(2000000, '2014-03-31 19:04:18.157', 'AAA', 0),
(3000000, '2014-03-31 19:04:18.157', 'AAA', 500),
(3000000, '2014-03-31 19:04:18.157', 'BBB', 500),
(4000000, '2014-03-31 19:04:18.157', 'AAA', 700);

我正在尝试按以下顺序为每个“ key_number”记录1条记录:

  1. 最新key_date
  2. 单位数量更多
  3. 如果有完全相同的副本,请使用最新的ID

因此,从上面的示例中,我希望得到以下结果:

1   2014-03-31 19:10:17.1100000 1000000 AAA 300
5   2014-03-31 19:04:18.1570000 2000000 AAA 100
8   2014-03-31 19:04:18.1570000 3000000 BBB 500
9   2014-03-31 19:04:18.1570000 4000000 AAA 700

我试图避免使用游标或临时表,这可能吗? 到目前为止,我有点像:

SELECT i.* FROM import_tbl i
inner join 
 (select key_number, max(key_date) as key_date, max(units) as units 
    from import_tbl  
    group by key_number) as latest
 on latest.key_number = i.key_number and latest.key_date = i.key_date

但是不太正确。 小提琴:http://sqlfiddle.com/#!18/f3e08/1

4 个答案:

答案 0 :(得分:2)

您可以对TOP TIES进行相同的操作,但是个人而言,我不喜欢它的语法,我的赌注是row_number:

select *
from (
select *, 
row_number() over(partition by key_number order by key_date DESC,  units desc, id desc) rn
from import_tbl
) a
where rn = 1

答案 1 :(得分:2)

它几乎完美地定义为ROW_NUMBER()的示例:

WITH cte AS (
    SELECT
        *,
        ROW_NUMBER() OVER (PARTITION BY key_number ORDER BY key_date DESC, units DESC, ID DESC) AS order_id
    FROM
        import_fbl)
SELECT
    *
FROM
    cte
WHERE
    order_id = 1;

答案 2 :(得分:2)

这是top / tie解决方案,由于缺少括号,因此我更喜欢:

select top 1 * with ties
from import_tbl
order by row_number() over(partition by key_number order by key_date desc, units desc, id desc)

答案 3 :(得分:1)

您还可以将subquery correlation 方法结合使用:

select i.*
from import_tbl i
where id = (select top 1 i1.id 
            from import_tbl i1
            where i.key_number = i1.key_number 
            order by i1.key_date desc, i1.units desc, i1.id desc
           );