我有桌子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
答案 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
答案 2 :(得分:0)
从问题标题开始:
如何从分区中给定的行日期中获取最近一个月的日期?
这是专门针对以下事实:根据Edits 1至Edit 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;