Using the lag function to find a moving average in SQL - sql

I need to find a moving average for the previous 12 rows. I need to have my result set look like this.
t Year Month Sales MovingAverage
1 2010 3 20 NULL
2 2010 4 22 NULL
3 2010 5 24 NULL
4 2010 6 25 NULL
5 2010 7 23 NULL
6 2010 8 26 NULL
7 2010 9 28 NULL
8 2010 10 26 NULL
9 2010 11 29 NULL
10 2010 12 27 NULL
11 2011 1 28 NULL
12 2011 2 30 NULL
13 2011 3 27 25.67
14 2011 4 29 26.25
15 2011 5 26 26.83
For row 13 I need to average rows 1 to 12 and have the result returned in row 13 column MovingAverage. Rows 1-12 have a MovingAverage of NULL because there should be at least 12 previous rows for the calculation. Rows t, Year, Month, and Sales already exist. I need to create the MovingAverage row. I am using postgreSQL but the syntax should be very similar.

Don't use the lag() function. There is a build in moving average function. Well, almost:
select t.*, avg(sales) over (order by t range between 12 preceding and current row
from table t;
The problem is that this will produce an average for the first 11 months. To prevent that:
select t.*,
(case when row_number() over (order by t) >= 12
then avg(sales) over (order by t range between 12 preceding and current row
end) as MovingAvg
from table t;
Note that the syntax rows between instead of range between would be very similar for this query.

Related

SQL query to Find highest value in table and sum the corresponding value

I would like to group Highest values in month column group by year and Sum the value column
value
Year
Month
4
2019
10
1
2019
11
5
2019
11
1
2019
11
1
2019
12
8
2019
12
1
2019
12
1
2020
1
10
2020
1
3
2021
1
2
2021
2
11
2021
2
1
2021
2
3
2021
2
2
2021
3
In above table I would like to extract highest value of month group by year
in year 2019 highest month is 12 so there are 3 rows and sum of value column will be 10
The output should be
value
Year
Month
10
2019
12
11
2020
1
2
2021
3
supposing that the table is called "example_table" you can use the following query:
select sum(example_table.value), example_table.year, example_table.month
from example_table
join (
select year, max(month) "month"
from example_table
group by year
) sub on example_table.year = sub.year and example_table.month = sub.month
group by example_table.year, example_table.month
order by example_table.year

Count by unique values in other fields in Oracle SQL

I have table like this:
Year Month Type
2013 4 31
2013 3 31
2014 5 40
2014 6 41
2015 5 31
2015 7 40
2013 4 31
2013 3 31
2014 5 40
2014 6 41
2015 5 31
2015 7 40
2013 4 31
2013 3 31
I would like to count number of appearance of each combination. So output should be something like this:
Year Month Type Count_of_appearance
2013 3 31 3
2013 4 31 3
etc..
I've been using something like:
SELECT Year,
Month,
Type,
(SELECT COUNT (*)
FROM myTable
WHERE (...im lost in defining a condition in order to make this work...)
AS Count_of_appearance
FROM employee;
I'm lost at defining functional WHERE clause.
Problem is I a have a lot of fields like this and a lot of unique values. Table is 8Gb big.
You are looking for GROUP BY:
SELECT Year, Month, Type, COUNT(*) AS Count_of_appearance
FROM employee
GROUP BY Year, Month, Type
ORDER BY Year, Month, Type;
To ensure that the results are in the right order, you should include an ORDER BY as well.

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;

SQL Query Return 0 on weeks in between

i have this query that works , but the result is not like i want
returns only year and weeks that has data , i want to return 0 to the result
for example this returns
year week totalstop
2017 50 7
2018 1 3
2018 3 5
but i want to return
year week totalstop
2017 50 7
2017 51 0
2017 52 0
2018 1 3
2018 2 0
2018 3 5
and so on
here is the current query
SELECT year(Stopdate)[year],datepart(week,date1) [week],sum(stop) totalstop
from Table1 where
building in (select item from dbo.fn_Split('A1,A2,A3,A4,A5',','))
and
date1 between '2017-12-12' and '2018-05-08'
and grp = 1
group by year(date1),datepart(week,date1)
order by year(date1),[week]
iam using ms sql-server 2016
need help to modify it to my needs as iam out of ideas atm.

Aggregate values with multiple conditions

I've searched the forum but can't quite find what I'm looking for. Apologies if this has already been answered.
I have a table with the following example values:
FY Period Version Value
2013 3 1 9954
2013 3 2 9954
2013 4 1 11498
2013 4 2 11498
2013 4 3 11498
2014 1 1 448
2014 1 2 448
2014 1 3 0
2014 2 1 3150
2014 2 2 3150
2014 3 1 0
2014 3 2 0
2014 3 3 5059
2014 4 1 11118
2014 4 2 0
2014 4 3 11118
I'm looking to sum the values for the highest version number, within each period and each FY, so the expected result for this particular data set would be:
(9954 + 11498 + 0 + 3150 + 5059 + 11118) = 40,779
I've done something similar previously with the over partition approach but i can't get it to work on this data set. Any pointers would be greatly appreciated.
A simple approach is to use row_number():
select sum(value)
from (select t.*,
row_number() over (partition by fy, period order by version desc) as seqnum
from table t
) t
where seqnum = 1;