Enter missing month and calculate running total in one stored procedure - sql

How can I select data from this table
Yr Month El1 Value
---- ------ ------- ------
2017 2 AT010 100
2017 3 AT010 100
2017 4 AT010 50
2017 5 AT010 150
2017 3 BE020 10
.......
and insert it into another table in the following way
Yr Month El1 Value
---- ------ ------- ------
2017 0 AT010 0
2017 1 AT010 0
2017 2 AT010 100
2017 3 AT010 200
2017 4 AT010 250
2017 5 AT010 400
2017 6 AT010 400
2017 7 AT010 400
2017 8 AT010 400
2017 9 AT010 400
2017 10 AT010 400
2017 11 AT010 400
2017 12 AT010 400
2017 0 BE020 0
2017 1 BE020 0
2017 2 BE020 0
2017 3 BE020 10
2017 4 BE020 10
2017 5 BE020 10
2017 6 BE020 10
2017 7 BE020 10
2017 8 BE020 10
2017 9 BE020 10
2017 10 BE020 10
2017 11 BE020 10
2017 12 BE020 10
.......
I am trying to insert missing months from 0 to 12 and calculate running total at the same time.
I used this suggestion for running total calculation; however, I can't figure out how to enter missing month.
This code will be used in the stored procedure for a daily ETL job.

Hmmm . . . Generate the rows and then use left join or outer apply to bring in the values. Here is one way:
with yyyymm as (
select 2017 as yr, 1 as mom
union all
select yr, mon + 1
from yyyymm
where mon + 1 <= 12
)
select yyyymm.yr, yyyymm.mon, coalesce(e.el1, 0) as el1
from yyyymm cross join
(select distinct el1 from t) e outer apply
(select sum(t.value)
from t
where t.el1 = e.el1 and
t.yr = yyyy.yr and
t.month <= yyyy.mon
) tt
order by e.el1, yyyy.yr, yyyy.month;

Related

Loop Record in Oracle

I have a Table called TaxAmount. It has 3 columns(ID, Year, Amount). refer the below image.
I want to divide each row into 12 months. I attached a sample image below.
I'm new in Oracle side. please help me to write a Oracle Query to display the above result.
I tried ROWNUM. But No luck.
Here's one option:
SQL> select id, year, column_value as month, amount
2 from taxamount cross join
3 table(cast(multiset(select level from dual
4 connect by level <= 12
5 ) as sys.odcinumberlist))
6 order by id, year, month;
ID YEAR MONTH AMOUNT
---------- ---------- ---------- ----------
1 2022 1 100
1 2022 2 100
1 2022 3 100
1 2022 4 100
1 2022 5 100
1 2022 6 100
1 2022 7 100
1 2022 8 100
1 2022 9 100
1 2022 10 100
1 2022 11 100
1 2022 12 100
2 2022 1 200
2 2022 2 200
2 2022 3 200
2 2022 4 200
2 2022 5 200
2 2022 6 200
2 2022 7 200
2 2022 8 200
2 2022 9 200
2 2022 10 200
2 2022 11 200
2 2022 12 200
3 2022 1 150
3 2022 2 150
3 2022 3 150
3 2022 4 150
3 2022 5 150
3 2022 6 150
3 2022 7 150
3 2022 8 150
3 2022 9 150
3 2022 10 150
3 2022 11 150
3 2022 12 150
36 rows selected.
SQL>

Transposing multiple related columns

While transposing single columns is pretty straight forward I need to transpose a large amount of data with 3 sets of , 10+ related columns needed to be transposed.
create table test
(month int,year int,po1 int,po2 int,ro1 int,ro2 int,mo1 int,mo2 int, mo3 int);
insert into test
values
(5,2013,100,20,10,1,3,4,5),(4,2014,200,30,20,2,4,5,6),(6,2015,200,80,30,3,5,6,7) ;
select * FROM test;
gives
month
year
po1
po2
ro1
ro2
mo1
mo2
mo3
5
2013
100
20
10
1
3
4
5
4
2014
200
30
20
2
4
5
6
6
2015
200
80
30
3
5
6
7
Transposing using UNPIVOT
select
month, year,
PO, RO, MO
from ( SELECT * from test) src
unpivot
( PO for Description in (po1, po2))unpiv1
unpivot
(RO for Description1 in (ro1, ro2)) unpiv2
unpivot
(MO for Description2 in (mo1, mo2, mo3)) unpiv3
order by year
Gives me this
month
year
PO
RO
MO
5
2013
100
10
3
5
2013
100
10
4
5
2013
100
10
5
5
2013
100
1
3
5
2013
100
1
4
5
2013
100
1
5
5
2013
20
10
3
5
2013
20
10
4
5
2013
20
10
5
5
2013
20
1
3
5
2013
20
1
4
5
2013
20
1
5
4
2014
200
20
4
4
2014
200
20
5
4
2014
200
20
6
4
2014
200
2
4
4
2014
200
2
5
4
2014
200
2
6
4
2014
30
20
4
4
2014
30
20
5
4
2014
30
20
6
4
2014
30
2
4
4
2014
30
2
5
4
2014
30
2
6
6
2015
200
30
5
6
2015
200
30
6
6
2015
200
30
7
6
2015
200
3
5
6
2015
200
3
6
6
2015
200
3
7
6
2015
80
30
5
6
2015
80
30
6
6
2015
80
30
7
6
2015
80
3
5
6
2015
80
3
6
6
2015
80
3
7
I will like to turn it to something like this. Is that possible?
month
year
PO
RO
MO
5
2013
100
10
3
5
2013
20
1
4
5
2013
0
0
5
4
2014
200
20
4
4
2014
30
2
5
4
2014
0
0
6
6
2015
200
30
5
6
2015
80
3
6
6
2015
0
0
7
Maybe use a query like below which creates rows as per your design using CROSS APPLY
select month,year,po,ro,mo from
test cross apply
(values (po1,ro1,mo1), (po2,ro2,mo2),(0,0,mo3))v(po,ro,mo)
see demo here
Unpivot acts similar as union,Use union all in your case
SELECT month,
year,
po1 AS PO,
ro1 AS RO,
mo1 AS MO
FROM test
UNION ALL
SELECT month,
year,
po2,
ro2,
mo2
FROM test
UNION ALL
SELECT month,
year,
0,
0,
mo2
FROM test

Add column value to next column in SQL

My sql table is
Week Year Applications
1 2017 0
2 2017 10
3 2017 20
4 2017 50
5 2017 0
1 2018 10
2 2018 0
3 2018 40
4 2018 50
5 2018 10
And I want SQL query which give below output
Week Year Applications
1 2017 0
2 2017 10
3 2017 30
4 2017 80
5 2017 80
1 2018 10
2 2018 10
3 2018 50
4 2018 100
5 2018 110
Can anyone help me to write below query?
You could use SUM() OVER to get cumulative sum:
SELECT *, SUM(Applications) OVER(PARTITION BY Year ORDER BY Week)
FROM tab
It looks like you want a cumulative sum:
select week, year,
sum(applications) over (partition by year order by week) as cumulative_applications
from t;

Joining From Differently Formatted Tables

Table 1:
ID Year Month
-----------------
1 2018 1
2 2018 1
3 2018 1
1 2018 2
2 2018 2
3 2018 2
Table 2:
ID Year Jan Feb Mar
------------------------
1 2018 100 200 300
2 2018 200 400 300
3 2018 200 500 700
How can I join these two tables even though they are laid out differently?
I was exploring a case join but that doesn't seem to be exactly what I need.
I'd like my output to be:
ID Year Month Data
1 2018 1 100
2 2018 1 200
3 2018 1 200
1 2018 2 200
2 2018 2 400
3 2018 2 500
1 2018 3 300
2 2018 3 300
3 2018 3 700
So, firstly we get TableB in the right format:
SELECT B.ID, B.Year, B.MonthValue
INTO TableB_New
FROM TableB T
UNPIVOT
(
MonthValue FOR Month IN (Jan, Feb, Mar)
) AS B
And then you do the join. Good Luck!

SQL: Populating missing months and values

I have a table that looks like the following:
Accountno | MonthPeriod | YearPeriod | Value | StartYear | StartMonth | EndYear | Endmonth
---------- ------------- ------------ ------- ----------- ------------ --------- --------
210 4 2015 100 2015 1 2016 5
210 2 2016 200 2015 1 2016 5
300 4 2015 50 2015 1 2016 5
300 2 2016 100 2015 1 2016 5
I am looking for a way to fill in the missing months and years between the startmonth/startyear and endmonth/endyear, where the values for the newly populated entries will be of the previously populated values - populating the values backwards if that makes any sense? And for the entries towards the endyear/endmonth the accountno's last value (As the desired output table below)
Accountno | MonthPeriod | YearPeriod | Value | StartYear | StartMonth | EndYear | Endmonth
---------- ------------- ------------ ------- ----------- ------------ --------- --------
210 1 2015 100 2015 1 2016 5
210 2 2015 100 2015 1 2016 5
210 3 2015 100 2015 1 2016 5
210 4 2015 200 2015 1 2016 5
210 5 2015 200 2015 1 2016 5
210 6 2015 200 2015 1 2016 5
210 7 2015 200 2015 1 2016 5
210 8 2015 200 2015 1 2016 5
210 9 2015 200 2015 1 2016 5
210 10 2015 200 2015 1 2016 5
210 11 2015 200 2015 1 2016 5
210 12 2015 200 2015 1 2016 5
210 1 2016 200 2015 1 2016 5
210 2 2016 200 2015 1 2016 5
210 3 2016 200 2015 1 2016 5
210 4 2016 200 2015 1 2016 5
210 5 2016 200 2015 1 2016 5
300 1 2015 50 2015 1 2016 5
300 2 2015 50 2015 1 2016 5
300 3 2015 50 2015 1 2016 5
300 4 2015 50 2015 1 2016 5
300 5 2015 100 2015 1 2016 5
300 6 2015 100 2015 1 2016 5
300 7 2015 100 2015 1 2016 5
300 8 2015 100 2015 1 2016 5
300 9 2015 100 2015 1 2016 5
300 10 2015 100 2015 1 2016 5
300 11 2015 100 2015 1 2016 5
300 12 2015 100 2015 1 2016 5
300 1 2016 100 2015 1 2016 5
300 2 2016 100 2015 1 2016 5
300 3 2016 100 2015 1 2016 5
300 4 2016 100 2015 1 2016 5
300 5 2016 100 2015 1 2016 5
I tried manipulating the following code for my situation but did not exceed:
CREATE TABLE TEST( Month tinyint, Year int, Value int)
INSERT INTO TEST(Month, Year, Value)
VALUES
(1,2013,100),
(4,2013,101),
(8,2013,102),
(2,2014,103),
(4,2014,104)
DECLARE #Months Table(Month tinyint)
Insert into #Months(Month)Values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10), (11),(12);
With tblValues as (
select Rank() Over (ORDER BY y.Year, m.Month) as [Rank],
m.Month,
y.Year,
t.Value
from #Months m
CROSS JOIN ( Select Distinct Year from Test ) y
LEFT JOIN Test t on t.Month = m.Month and t.Year = y.Year
)
Select t.Month, t.Year, COALESCE(t.Value, t1.Value) as Value
from tblValues t
left join tblValues t1 on t1.Rank = (
Select Max(tmax.Rank)
From tblValues tmax
Where tmax.Rank < t.Rank AND tmax.Value is not null)
Order by t.Year, t.Month
Any assistance will be greatly appreciated!