如何从分区中给定的行日期中获取最近的上个月的日期?

时间:2019-11-27 18:07:58

标签: sql oracle

我有桌子A

Item     Date    

a        01-01-2000   
a        10-05-2000    
a        12-02-2000    
b        01-01-2000    
b        01-31-2000    
b        02-01-2000    
c        01-01-2000  

我想要此输出,即同一项目给定行的最接近的上一个日期

Item     Date          closest_day

a        01-01-2000    null
a        10-05-2000    01-01-2000
a        12-02-2000    10-05-2000
b        01-01-2000    null
b        01-31-2000    null
b        02-01-2000    01-31-2000
c        01-01-2000    null

4 个答案:

答案 0 :(得分:1)

尝试

with t as(
select 'a' c,to_date('01.01.2000','mm.dd.yyyy') d from dual
union all   
select 'a' ,to_date('10.05.2000','mm.dd.yyyy')  from dual    
union all   
select 'a' ,to_date('12.02.2000','mm.dd.yyyy')  from dual    
union all   
select 'b' ,to_date('01.01.2000','mm.dd.yyyy')  from dual    
union all   
select 'b' ,to_date('01.31.2000','mm.dd.yyyy')  from dual   
union all   
select 'b' ,to_date('02.01.2000','mm.dd.yyyy')  from dual    
union all   
select 'c' ,to_date('01.01.2000','mm.dd.yyyy')  from dual
)
select t.c,t.d,LAG (t.d) over ( partition by t.c order by t.d ) from t 

最近的日期必须在其他月份? 好的

 with t as(
select 'a' c,to_date('01.01.2000','mm.dd.yyyy') d from dual
union all   
select 'a' ,to_date('10.05.2000','mm.dd.yyyy')  from dual    
union all   
select 'a' ,to_date('12.02.2000','mm.dd.yyyy')  from dual    
union all   
select 'b' ,to_date('01.01.2000','mm.dd.yyyy')  from dual    
union all   
select 'b' ,to_date('01.31.2000','mm.dd.yyyy')  from dual   
union all   
select 'b' ,to_date('02.01.2000','mm.dd.yyyy')  from dual    
union all   
select 'c' ,to_date('01.01.2000','mm.dd.yyyy')  from dual
)
select c,d,case when trunc(d,'Month')<>trunc(closest_d,'Month') then closest_d else null end closest_d  from(
select t.c,t.d,LAG (t.d) over ( partition by t.c order by t.d ) closest_d from t 
)  

答案 1 :(得分:0)

您可以使用包含连接条件内日期之间不等式的自左连接:

with t2 as
(
select t1.Item,t1."Date" as t1_Date, t2."Date" as t2_Date
  from t t1
  left join t t2 on t1."Date">t2."Date" and t1.Item = t2.Item
)
select Item, t1_Date as "Date", max(t2_Date) as "Closest Day"
  from t2
 group by Item, t1_Date 
 order by Item, t1_Date

Demo

答案 2 :(得分:0)

从问题标题开始:

  

如何从分区中给定的行日期中获取最近一个月的日期?

这是专门针对以下事实:根据Edits 1Edit 3中的预期结果,前一个值应该在“上一个”月份中,而不是与行日期相同的月份中。 / p>

Oracle设置

CREATE TABLE test_data ( item, "date" ) AS
SELECT 'A', DATE '2000-01-01' FROM DUAL UNION ALL
SELECT 'A', DATE '2000-10-05' FROM DUAL UNION ALL
SELECT 'A', DATE '2000-12-02' FROM DUAL UNION ALL
SELECT 'B', DATE '2000-01-01' FROM DUAL UNION ALL
SELECT 'B', DATE '2000-01-31' FROM DUAL UNION ALL
SELECT 'B', DATE '2000-02-01' FROM DUAL UNION ALL
SELECT 'C', DATE '2000-01-01' FROM DUAL;

查询

SELECT t.*,
       ( SELECT MAX( "date" )
         FROM   test_data p
         WHERE  p.item = t.item
         AND    p."date" < TRUNC( t."date", 'MM' )
       ) AS prev_date
FROM   test_data t

输出

ITEM | date                | PREV_DATE          
:--- | :------------------ | :------------------
A    | 2000-01-01 00:00:00 | null               
A    | 2000-10-05 00:00:00 | 2000-01-01 00:00:00
A    | 2000-12-02 00:00:00 | 2000-10-05 00:00:00
B    | 2000-01-01 00:00:00 | null               
B    | 2000-01-31 00:00:00 | null               
B    | 2000-02-01 00:00:00 | 2000-01-31 00:00:00
C    | 2000-01-01 00:00:00 | null               

db <>提琴here

答案 3 :(得分:0)

您可以使用窗口函数来执行此操作-如果我假设您希望每行当前日期为之前,这使用range窗口定义:

SELECT t.*,
       MAX("date") OVER (PARTITION BY item
                         ORDER BY TRUNC(t."date", 'MON')
                         RANGE BETWEEN UNBOUNDED PRECEDING AND INTERVAL '1' MONTH PRECEDING
                        ) AS prev_date
FROM test_data t;

Here是db <>小提琴。

如果您特别想要上一个日历月的结果,则:

SELECT t.*,
       MAX("date") OVER (PARTITION BY item
                         ORDER BY TRUNC(t."date", 'MON')
                         RANGE BETWEEN INTERVAL '1' MONTH PRECEDING AND INTERVAL '1' MONTH PRECEDING
                        ) AS prev_date
FROM test_data t;