Oracle - 从一组行中获取最小和最大日期

Posted

技术标签:

【中文标题】Oracle - 从一组行中获取最小和最大日期【英文标题】:Oracle - Get min & max date from group of rows 【发布时间】:2019-01-11 01:59:33 【问题描述】:

初始数据:

select t.AGENHI, t.TACTHI, t.DTEFHI, t.DTFIHI            
      from mytable t
      where agenhi = '81000040' ;

AGENHI      TACTHI   DTEFHI     DTFIHI            
81000040    1        24/02/92   08/03/92
81000040    1        09/03/92   28/02/93
81000040    1        01/03/93   31/05/97
81000040    0,8      01/06/97   31/12/97
81000040    1        01/01/98   31/12/98
81000040    1        01/01/99   

使用这个查询:

SELECT AGENHI, 
DECODE(TACTHI, 0.05, '005', 0.07, '007', 0.1, '010', 0.137, '013', 0.15, 
'015', 0.2, '020', 0.21, '021', 0.23, '023', 0.25, '025', 0.3, '030', 
0.34, '034', 0.4, '040', 0.45, '045', 0.5, '050', 0.6, '060', 0.63, 
'063',0.7, '070', 0.75, '075', 0.8,'080', 0.84, '084',0.9, '090', 1, '100', 
TACTHI) as QUOTITE,
dtefhi as START_DATE,
DECODE(LEAD (DTFIHI, 1) OVER (ORDER BY DTFIHI NULLS LAST) ,null, 
to_date('31122099','ddmmyyyy'), LEAD (DTFIHI, 1) OVER (ORDER BY DTFIHI NULLS 
LAST)) AS END_DATE
FROM MYTABLE 
WHERE AGENHI = '81000040' AND DTFIHI IS NOT NULL;

我明白了:

AGENHI      QUOTITE     START_DATE    END_DATE
81000040    100         08/03/92      28/02/93
81000040    100         28/02/93      31/05/97
81000040    100         31/05/97      31/12/97
81000040    080         31/12/97      31/12/98
81000040    100         31/12/98      31/12/99

但我需要在下一行相同时对“QUOTITE”进行分组,并显示第一行的开始日期和最后一行的日期。

预期结果:

AGENHI      QUOTITE     START_DATE    END_DATE
81000040    100         24/02/92      31/12/97
81000040    080         01/06/97      31/12/98
81000040    100         01/01/98      31/12/99

gordon 提供的解决方案:

选择 agenhi, tacthi, min(dtfihi) 作为 start_date, 领先(max(dtfihi))超过(按agenhi,seqnum-seqnum_2 order by max(dtfihi))作为end_date 从(选择 t.*, row_number() over(按 agenhi order by dtfihi 分区)作为 seqnum, row_number() over (agenhi 分区,dtfihi tacthi order) as seqnum_2 来自 HIA@CHRONOS_TO_S2.WORLD t 其中 agenhi = '81000040' 并且 dtfihi 不为空 ) 吨 按 agenhi 分组,(seqnum - seqnum_2),tacthi;

结果:

81000040    1   08/03/92   null 
81000040    1   31/12/98   null   
81000040    0,8 31/12/97   null 

我怎样才能得到 end_date ? 如果我找到解决方案,我会看看谢谢!

【问题讨论】:

这种问题称为间隙和孤岛。对此有很多要求,您可以查找。您必须先获得quotite,然后从row_number() over (order by dtfihi) 中减去row_number() over (partition by quotite order by dtfihi) 以获得组密钥。然后聚合获得每个组键的最小和最大日期。最后使用LEAD 调整结束日期。 【参考方案1】:

您遇到了缝隙和孤岛问题。我会从原始数据开始,所以是这样的:

select agenhi, tacthi, min(dtfihi) as start_date,
       lead(min(dtfihi)) over (partition by agenhi order by min(dtfihi)) as end_date
from (select t.*,
             row_number() over (partition by agenhi, order by dtfihi) as seqnum,
             row_number() over (partition by agenhi, tacthi order by dtfihi) as seqnum_2
      from mytable t
      where agenhi = '81000040' an dtfihi IS NOT NULL
     ) t
group by agenhi, (seqnum - seqnum_2), tacthi;

您可以添加decode() 逻辑(我将其写为case 表达式),但这并没有真正改变解决方案。

【讨论】:

Just to add (for the OP): Gordon演示的找出主组行号(seqnum)和子组行号(seqnum_2)之间差异的技术在他们的回答中被称为Tabibitosan。我会在生成 row_numbers 的子查询中做减号,而不是在查询之外,因为这意味着在外部查询中输入更少,但这是个人喜好。 @Boneist 。 . .我已经将row_numbers() 留在子查询中,这样人们就可以看到他们的样子。我发现很难解释为什么差异可以识别这些群体。但是当你看到发生了什么时,大多数人都会有一个“啊哈”的时刻。 感谢您的帮助戈登!我的 end_date 只有空值……你能再帮帮我吗? :) @Beanl 。 . . partition by 中的组逻辑不正确。 @GordonLinoff 是的,我认为是这样的。我只是想向 OP 提供更多信息【参考方案2】:

@Boneist , @GordonLinoff 再次感谢您的帮助。

select 
agenhi, 
DECODE(TACTHI, 0.05, '005', 0.07, '007', 0.1, '010', 0.137, '013', 0.15, '015', 0.2, '020', 0.21, '021', 0.23, '023', 0.25, '025', 0.3, '030', 
0.34, '034', 0.4, '040', 0.45, '045', 0.5, '050', 0.6, '060', 0.63, '063',0.7, '070', 0.75, '075', 0.8,'080', 0.84, '084',0.9, '090', 1, '100', TACTHI) as QUOTITECPAGE,  
min(dtefhi) as start_date,
nvl(lead(min(dtfihi)) over (partition by agenhi order by min(dtfihi)), 
to_date('31122099','ddmmyyyy')) as end_date
from (select t.*,
         row_number() over (partition by agenhi order by dtfihi) as seqnum,
         row_number() over (partition by agenhi, tacthi order by dtefhi) as seqnum_2
  from HIA@CHRONOS_TO_S2.WORLD t
  where agenhi = '81000040' order by DTEFHI
 ) t
 group by agenhi, (seqnum - seqnum_2), tacthi;

【讨论】:

以上是关于Oracle - 从一组行中获取最小和最大日期的主要内容,如果未能解决你的问题,请参考以下文章

有没有办法从每组行中获取 2 行? [复制]

SQL选择具有最大和最小日期的行

如何确定一个值是不是在使用 Dplyr 的一组行中出现最多? [复制]

SQL ORACLE 从多个日期时间行中获取周数

如何从选定的表行中获取最小和最大数量?

python kayb算法之从一组序列当中获取一组与目标值最接近的算法