Write SQL
Query to fill the missing months with previous month’s salary?
Video
To achieve the desired output, we can use a combination
of WITH clause, Connect By and LEAD function to fill the missing months.
Here how we do it.
Example data
select '1' ename,'Jan-19' month,5000 salary from dual union all
select '1' ename,'Aug-19' month,10000 salary from dual union all
select '1' ename,'Dec-19' month,15000 salary from dual
),
next_month as (
select ename,month,salary,to_date(month,'MON-YY') as D,
lead(to_date(month,'MON-YY'),1) over(partition by ename order by to_date(month,'Mon-YY')) next_inc_month
from data
),
replicate as (
select ename,month,salary,D,next_inc_month,months_between(next_inc_month,d) tt,
nvl(months_between(next_inc_month,d),1) tt1
from next_month
)
select ename,to_char(add_months(d,r),'MON-YY') month ,salary from replicate,
lateral (select rownum-1 r from dual connect by level<=tt1);
--------------------------Result
WITH data AS (
SELECT '1' AS ename, 'May-19' AS month, 5000 AS salary
UNION ALL
SELECT '1' AS ename, 'Aug-19' AS month, 10000 AS salary
UNION ALL
SELECT '1' AS ename, 'Dec-19' AS month, 15000 AS salary
),
next_month AS (
SELECT ename, month, salary,
to_date(month, 'Mon-YY') AS D,
lead(to_date(month, 'Mon-YY'), 1) OVER (PARTITION BY ename ORDER BY to_date(month, 'Mon-YY')) AS next_inc_month
FROM data
),
replicate AS (
SELECT ename, month, salary, D, next_inc_month,
EXTRACT(MONTH FROM age(next_inc_month, D)) AS tt,
COALESCE(EXTRACT(MONTH FROM age(next_inc_month, D)), 1) AS tt1
FROM next_month
)
SELECT ename, to_char(D + (r * interval '1 month'), 'Mon-YY') AS month, salary
FROM replicate,
LATERAL generate_series(0, tt1 - 1) AS gs(r);
SELECT '1' AS ename, 'May-19' AS month, 5000 AS salary
UNION ALL
SELECT '1' AS ename, 'Aug-19' AS month, 10000 AS salary
UNION ALL
SELECT '1' AS ename, 'Dec-19' AS month, 15000 AS salary
),
next_month AS (
SELECT ename, month, salary,
CAST(CONVERT(DATE, '01-' + month, 106) AS DATE) AS D,
LEAD(CAST(CONVERT(DATE, '01-' + month, 106) AS DATE), 1) OVER (PARTITION BY ename ORDER BY CAST(CONVERT(DATE, '01-' + month, 106) AS DATE)) AS next_inc_month
FROM data
),
replicate AS (
SELECT ename, month, salary, D, next_inc_month,
DATEDIFF(MONTH, D, next_inc_month) AS tt,
ISNULL(DATEDIFF(MONTH, D, next_inc_month), 1) AS tt1
FROM next_month
)
SELECT ename, FORMAT(DATEADD(MONTH, r, D), 'MMM-yy') AS month, salary
FROM replicate
CROSS APPLY (SELECT TOP (tt1) ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) - 1 AS r FROM master..spt_values) AS x;
--------------------------Result
0 Comments
Thanks for your message.