【问题标题】:Retrieve max date for distinct IDs in a table [duplicate]检索表中不同 ID 的最大日期 [重复]
【发布时间】:2020-01-11 10:55:57
【问题描述】:

我的表 ABC 包含以下数据

Id  Name    Date      Execution id 
--  ----  ---------  -------------
1    AA   09SEP2019      11
1    AA   08SEP2019      22
1    AA   07SEP2019      33
2    BB   09SEP2019      44
2    BB   08SEP2019      55
2    BB   07SEP2019      66

我想为表中的每个不同 ID 获取其最大日期。所以结果集一定是这样的

Id Name     Date     Execution id 
-- ----  ---------  -------------
1   AA   09SEP2019      11
2   BB   09SEP2019      44

返回我需要的结果的查询

WITH MaxDate as (
   SELECT Id,Name,Max(Date) from ABC group by Id,Name
)
SELECT view1.*, view2.exection_id
from
       MaxDate view1,
       ABC     view2
WHERE
       view1.date=view2.date and
       view1.name=view2.name;

我不喜欢通过这种方式获取不同 ID 的最大日期。可能有另一种方法吗?可能有更简单的方法吗?

【问题讨论】:

    标签: sql oracle greatest-n-per-group


    【解决方案1】:

    一种方法是使用RANK:

    WITH cte AS (
      SELECT ABC.*, RANK() OVER(PARTITION BY Id,Name ORDER BY Date DESC) rnk
      FROM ABC 
    )
    SELECT *
    FROM cte
    WHERE rnk = 1
    ORDER BY id;
    

    【讨论】:

    • 谢谢。看起来它对我有用。
    【解决方案2】:

    您可以在一级查询中使用keep dense_rank last 执行此操作,只要您只希望保留一个或少数列:

    select id,
           name,
           max(date_) as date_,
           max(execution_id) keep (dense_rank last order by date_) as execution_id
    from abc
    group by id, name
    order by id;
    
            ID NAME DATE_      EXECUTION_ID
    ---------- ---- ---------- ------------
             1 AA   2019-09-09           11
             2 BB   2019-09-09           44
    

    如果 ID 和 name 并不总是相同,并且您希望 name 也是最新日期,则使用相同的模式:

    select id,
           max(name) keep (dense_rank last order by date_) as name,
           max(date_) as date_,
           max(execution_id) keep (dense_rank last order by date_) as execution_id
    from abc
    group by id
    order by id;
    

    与您的样本数据得到相同的结果。

    对于很多列,使用带有排名函数和过滤器的子查询(CTE 或内联视图)可能更简单(如@Lukasz 所示)。

    【讨论】:

    • 谢谢。 Lukasz 解决方案看起来也不错
    【解决方案3】:

    不存在:

    select t.* from ABC t
    where not exists (
      select 1 from ABC
      where "Id" = t."Id" and "Name" = t."Name" and "Date" > t."Date"
    )
    

    我使用and name = t.name 只是因为您的代码中有它。
    如果不需要,您可以将其删除。
    请参阅demo
    结果:

    Id | Name | Date      | Execution id
    -: | :--- | :---------| -----------:
     1 | AA   | 09-SEP-19 |           11
     2 | BB   | 09-SEP-19 |           44
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-11-09
      • 1970-01-01
      • 2014-01-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多