如果数据存在于两个不同的年份,则需要在表中找到月份之间存在差距的记录。我有像 id、value、month、year 这样的列。
Id, value, month,year
1, 123, oct, 2020
1, 128, nov, 2020
1, 127, jan ,2021
2, 121, Dec, 2020
2, 154, jan, 2021
我需要的输出:Id 1,因为月份有间隔(Dec is Missing for id=1)
我会构建一个日期并使用lag()
:
select t.*
from (select t.*,
lag(dte) over (partition by id order by dte) as prev_dte
from (select t.*,
to_date(year || '-' || month || '-01', 'YYYY-MON-DD') as dte
from t
) t
) t
where prev_dte <> dte - interval '1' month;
这是一个 db<>fiddle。
这是一种选择。阅读代码中的注释。
SQL> with test (id, value, month, year) as
2 -- sample data; you have that, don't type it
3 (select 1, 123, 'oct', 2020 from dual union all
4 select 1, 128, 'nov', 2020 from dual union all
5 select 1, 127, 'jan', 2021 from dual union all
6 select 2, 121, 'dec', 2020 from dual union all
7 select 2, 154, 'jan', 2021 from dual
8 ),
9 temp as
10 -- "convert" month and year to real date value
11 (select id,
12 value,
13 to_date(month ||' '|| year, 'mon yyyy', 'nls_date_language=english') datum
14 from test
15 ),
16 temp2 as
17 -- select difference in months between DATUM and next month (LEAD!)
18 (select id,
19 months_between
20 (datum,
21 to_date(month ||' '|| year, 'mon yyyy', 'nls_date_language=english') datum
22 ) diff
23 from temp
24 )
25 select distinct id
26 from temp2
27 where abs(diff) > 1;
ID
----------
1
SQL>
它可能会被压缩,但逐步的 CTE 会显示正在发生的事情。
Here is an example using the LAG function and finding rows where where the prior month is not one month behind (or non existent)
WITH
sample_data (Id,
VALUE,
month,
year)
AS
(SELECT 1, 123, 'oct', 2020 FROM DUAL
UNION ALL
SELECT 1, 128, 'nov', 2020 FROM DUAL
UNION ALL
SELECT 1, 127, 'jan', 2021 FROM DUAL
UNION ALL
SELECT 2, 121, 'Dec', 2020 FROM DUAL
UNION ALL
SELECT 2, 154, 'jan', 2021 FROM DUAL)
SELECT DISTINCT id
FROM (SELECT sd.id,
CASE
WHEN ADD_MONTHS (TO_DATE (sd.year || sd.month, 'YYYYMON'), -1) =
TO_DATE (
LAG (sd.year || sd.month)
OVER (
PARTITION BY id
ORDER BY
sd.year, EXTRACT (MONTH FROM TO_DATE (sd.month, 'MON'))),
'YYYYMON')
OR LAG (sd.id)
OVER (
PARTITION BY id
ORDER BY sd.year, EXTRACT (MONTH FROM TO_DATE (sd.month, 'MON')))
IS NULL
THEN
'Y'
ELSE
'N'
END AS valid_prev_month
FROM sample_data sd)
WHERE valid_prev_month = 'N';