【问题标题】:Find max of a date column and display that value for all rows of the group查找日期列的最大值并为组的所有行显示该值
【发布时间】:2021-05-17 00:05:29
【问题描述】:

我有一个表,其中有 2 个日期列,总共 4 个 - valid_from_dt 和 valid_to_dt。其他 2 列是 itm_no 和 price。我需要在 itm_no、price 和一系列连续日期中找到 valid_to_dt 的最大值。这将使用一定程度的差距和孤岛解决方案。然后必须在该组的所有行中显示该最大值。我会分享表格的代码。

create table price_tab (itm_no varchar2(10), price number, valid_from_dt date, valid_to_dt date);

insert into price_tab values ('A001', 83, '01-JAN-21', '05-JAN-21');
insert into price_tab values ('A001', 83, '06-JAN-21', '12-JAN-21');
insert into price_tab values ('A001', 98, '13-JAN-21', '17-JAN-21');
insert into price_tab values ('A001', 83, '19-JAN-21', '24-JAN-21');
insert into price_tab values ('A001', 83, '25-JAN-21', '30-JAN-21');
insert into price_tab values ('A002', 71, '01-JAN-21', '11-JAN-21');
insert into price_tab values ('A001', 83, '31-JAN-21', '04-FEB-21');
insert into price_tab values ('A001', 77, '17-FEB-21', '25-FEB-21');

如上所示,从 1 月 1 日到 1 月 12 日,itm_no A001 的价格为 83 有 2 行。因此,第一行的 max_valid_to 应为 1 月 12 日。价格为 83 的 itm_no A001 也可在 1 月 19 日至 2 月 4 日期间提供。 1 月 13 日至 18 日,A001 价格为 83 的差距。

我有查询来获取 itm_no、价格和一系列连续日期的组的 max valid_to_dt:

select itm_no, price,  max(valid_to_dt) from (
select t.*,
       row_number() over(partition by itm_no order by valid_from_dt, valid_to_dt) rn1
      ,row_number() over(partition by itm_no, price order by valid_from_dt, valid_to_dt) rn2
from price_tab t ) x group by itm_no, price, rn1-rn2 order by 1, 3;

但我无法找到一种方法来获取最大 valid_to_dt 并将其显示为具有 itm_no、价格和连续日期系列的所有行。有人可以指导我吗?

【问题讨论】:

  • edit您的问题包括您的预期输出。
  • 我对我的问题进行了编辑。添加了一个额外的列和另一个数据集。它基本上是相同的问题,但表有一个额外的列和新的数据场景。我应该发布一个新问题还是编辑上述问题?
  • 好的,我会继续更新问题。如果有人想让我发新帖子,我会的。

标签: sql oracle


【解决方案1】:

您似乎希望为价格相同的每组连续行返回最后一个VALID_TO_DT,并在该组行中的所有行上显示。

从 Oracle 12 开始,您可以使用MATCH_RECOGNIZE

SELECT itm_no,
       price,
       valid_from_dt,
       MAX( valid_to_dt ) OVER ( PARTITION BY itm_no, mno ) AS valid_to_dt
FROM   price_tab
MATCH_RECOGNIZE(
  PARTITION BY itm_no
  ORDER BY valid_from_dt
  MEASURES
    MATCH_NUMBER() AS mno
  ALL ROWS PER MATCH
  PATTERN ( new_price same_price* )
  DEFINE
    same_price AS PREV(price) = price
)

或者,您可以使用:

SELECT itm_no,
       price,
       valid_from_dt,
       MAX(valid_to_dt) OVER ( PARTITION BY itm_no, mno ) AS valid_to_dt
FROM   (
  SELECT t.*,
         row_number() over(
           partition by itm_no order by valid_from_dt, valid_to_dt
         )
         - row_number() over(
              partition by itm_no, price order by valid_from_dt, valid_to_dt
         ) AS mno
  FROM   price_tab t
)
ORDER BY itm_no, valid_from_dt;

对于您的样本数据,输出:

ITM_NO PRICE VALID_FROM_DT VALID_TO_DT
A001 83 01-JAN-21 12-JAN-21
A001 83 06-JAN-21 12-JAN-21
A001 98 13-JAN-21 17-JAN-21
A001 83 19-JAN-21 04-FEB-21
A001 83 31-JAN-21 04-FEB-21
A001 83 25-JAN-21 04-FEB-21
A001 77 17-FEB-21 25-FEB-21
A002 71 01-JAN-21 11-JAN-21

db小提琴here

【讨论】:

  • 是的,示例数据输出正是您发布的内容。我会用它来提出我的问题。
  • 这真的很有帮助。我得到了想要的输出。由于 Oracle 版本是 11,因此第二种方法很有效。我点击了upvote,但我没有15个声望点,所以它无法获得upvote。我希望有一些选项可以将您的帖子作为答案。如果有的话请告诉我,我会很乐意这样做的。
【解决方案2】:

如果我理解正确,您只希望您的查询使用窗口函数而不是聚合:

select t.*,
       max(valid_to_dt) over (partition by itm_no, price, rn1 - rn2)
from (select t.*,
             row_number() over(partition by itm_no order by valid_from_dt, valid_to_dt) as rn1,
             row_number() over(partition by itm_no, price order by valid_from_dt, valid_to_dt) as rn2
      from price_tab t
     ) t ;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-02-15
    • 2023-03-10
    • 1970-01-01
    • 2019-11-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-20
    相关资源
    最近更新 更多