简体   繁体   English

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

[英]How can I get the date with the closest previous month from a given row date in a partition?

I have the table A 我有桌子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  

i want this output, the closest previous date of the given row for the same item 我想要此输出,同一项目的给定行的最接近的上一个日期

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

try this 尝试这个

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 

closest date must be in a different month? 最接近的日期必须在不同的月份? ok

 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 
)  

You can use a self-left join containing inequality among dates within the join condition : 您可以使用包含连接条件内日期之间不等式的自左连接:

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 演示版

i want this output, the closest previous date of the given row for the same item 我想要此输出,同一项目的给定行的最接近的上一个日期

That's exactly what window function lag() does: 这正是窗口函数lag()作用:

select
    t.*, 
    lag(date) over(partition by item order by date) closest_day
from mytable t

From the question title: 从问题标题:

How can I get the date with the closest previous month from a given row date in a partition? 如何从分区中给定的行日期中获取最近的上个月的日期?

This is specifically addressing the fact that the previous value should be in a "previous" month and not in the same month as the row's date as per the expected results in Edits 1 through Edit 3 . 这是专门针对以下事实:根据编辑1编辑3中的预期结果,前一个值应位于“上一个”月中,而不应与行日期位于同一月中。

Oracle Setup : 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;

Query : 查询

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

Output : 输出

\nITEM | 项目| date | 日期| PREV_DATE PREV_DATE          \n:--- | :--- | :------------------ | :------------------ | :------------------ :------------------\nA | A | 2000-01-01 00:00:00 | 2000-01-01 00:00:00 | null 空值               \nA | A | 2000-10-05 00:00:00 | 2000-10-05 00:00:00 | 2000-01-01 00:00:00 2000-01-01 00:00:00\nA | A | 2000-12-02 00:00:00 | 2000-12-02 00:00:00 | 2000-10-05 00:00:00 2000-10-05 00:00:00\nB | B | 2000-01-01 00:00:00 | 2000-01-01 00:00:00 | null 空值               \nB | B | 2000-01-31 00:00:00 | 2000-01-31 00:00:00 | null 空值               \nB | B | 2000-02-01 00:00:00 | 2000-02-01 00:00:00 | 2000-01-31 00:00:00 2000-01-31 00:00:00\nC | C | 2000-01-01 00:00:00 | 2000-01-01 00:00:00 | null 空值               \n

db<>fiddle here db <> 在这里拨弄

You can do this with window functions -- if I assume that you want the most recent date before the current month for each row. 您可以使用窗口函数来执行此操作-如果我假设您希望每一行的当前日期之前为最新日期。 This uses the range window definition: 这使用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 is a db<>fiddle. 是db <>小提琴。

If you specifically want the result from the previous calendar month, then: 如果您特别想要上一个日历月的结果,则:

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;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM