How to sum with specific range of records - sql

I have table
tax number yearmonth(int)
100 45 202105
2 45 202104
35 45 202102
47 45 202012
58 45 202005
I try to aggregate sum for every number by last 12 month
For instance 202105 - I need sum month between (202012 - 202001)
Main problem -> not every number has all 12 months
I tried over clause but it sums all 12 preceding records. It does not take into account missing year records.
case when yearmonth-lag(yearmonth,1) OVER ( order by number, yearmonth) <> (0) then
sum([tax]) OVER (
PARTITION BY [number]
ORDER BY yearmonth
Rows BETWEEN 11 PRECEDING AND CURRENT ROW ) end

Related

Is there a way to select first column from first row and add second column values to it for all remaining rows?

So I'm working with MS SQL and I have a selection table:
total
margin
date
45
-1
2022-01
45
0
2022-02
45
0
2022-03
45
1
2022-04
45
-1
2022-05
45
0
2022-06
What I need is to select firt total and add margin for each other months ignoring other totals like so:
total
margin
date
44
-1
2022-01
44
0
2022-02
44
0
2022-03
45
1
2022-04
44
-1
2022-05
44
0
2022-06
I've tried using LAG function but it ignores last change. For example at forth row it would take previous value of 45 and not 44.
Thanks for answers got what I need with:
first_value(total) over(order by [date] ROWS UNBOUNDED PRECEDING) + sum(margin) over(order by [date] ROWS UNBOUNDED PRECEDING) as total

sum of last 12 months of data where each month has 2 rows of data -- Spark SQL

so my dataset has two columns, one column for the date (that contains month start and month end date), second column contains the count
1-Nov-18 58
30-Nov-18 76
1-Dec-18 93
31-Dec-18 57
1-Jan-19 62
31-Jan-19 78
1-Feb-19 87
28-Feb-19 75
1-Mar-19 54
31-Mar-19 59
1-Apr-19 76
30-Apr-19 79
1-May-19 81
31-May-19 80
1-Jun-19 71
30-Jun-19 52
1-Jul-19 75
31-Jul-19 57
1-Aug-19 76
31-Aug-19 76
1-Sep-19 63
30-Sep-19 57
1-Oct-19 81
30-Oct-19 84
and so on..
i need my output as
Oct2019 1707
basically for month oct2019 i need sum for counts for records from nov'18 to oct'19 (last 12 months), similary for month nov2019 i would need sum of all records from Dec'18 to Nov'19. and so on for other months
I think what you are looking for is a Group By clause with a select count. I can't give you the perfect answer because I need more information about your schema... What is your Database name, Database Table, Column names...
SELECT `dateField`,SUM(`countField`)
FROM `TableName`
GROUP BY `dateField`;
You can also do a Group By Months like this:
GROUP BY YEAR('dateField`), MONTH(`dateField`)
I think you want aggregation and a window function with RANGE:
select date_trunc(date, 'MM') as mon, SUM(cnt) as month_cnt,
SUM(SUM(cnt)) OVER (ORDER BY MIN(date)
RANGE BETWEEN INTERVAL 11 MONTH PRECEDING AND CURRENT ROW
) as running_12_months
from t
group by date_trunc(date, 'MM');

Last 3 months average next to current month value in hive

I have a table which has the monthly sales values for each of the items. I need last 3 months average sales value next to the current month sales for each item.
Need to perform this operation in hive.
The sample input table looks like below
Item_ID Sales Month
A 4295 Dec-2018
A 245 Nov-2018
A 1337 Oct-2018
A 3290 Sep-2018
A 2000 Aug-2018
B 856 Dec-2018
B 1694 Nov-2018
B 4286 Oct-2018
B 2780 Sep-2018
B 3100 Aug-2018
The result table should look like this
Item_ID Sales_Current_Month Month Sales_Last_3_months_average
A 4295 Dec-2018 1624
A 245 Nov-2018 2209
B 856 Dec-2018 2920
B 1694 Nov-2018 3388.67
Assuming there is no missing months data, you can use avg window function to do this.
select t.*
,avg(sales) over(partition by item_id order by month rows between 3 preceding and 1 preceding) as avg_sales_prev_3_months
from tbl t
If month column is in a format different from yyyyMM, use an appropriate conversion so the ordering works as expected.

Is it possible to write an MDX query of the format "last x days of days of week"?

This is from a heavily manually maintained report that I am trying to automate a bit view an SSAS cube.
The report contains daily sales, and, among other things, a measure called "last 4 's". E.g., For Friday, October 16 the measure was the average sales over the last 4 Fridays.
Is there a way to construct this in MDX in way that can be placed in a calculated measure in an SSAS cube?
ps--In response to whytheq's question, yes, the date dimension includes day of week, which is an integer in which Sun = 1, Mon = 2 and so on to Sat = 7.
I see that I was slightly ambiguous above. By "last 4 Fridays" above I meant the 4 Fridays immediately preceding October 16, not the most recent 4 Fridays.
Agreed with whytheq, that more information may help us to create optimal solution. Anyway:
Solved if you have only flat days hierarchy:
+All
-2015/01/01
-2015/01/02
...
-2015/12/31
...
Logic could be like this:
rank all days
split by weeks
calculate last 4 for every day type
show result for every selected member
Example of flat hierarchy [Report Date].[Report Date].[Day] calculation:
with
member [Measures].[AllDaysRank] as Rank([Report Date].[Report Date].CurrentMember,[Report Date].[Report Date].[Day].Members)
member [Measures].[WeekDay] as ([Measures].[AllDaysRank]-(Int([Measures].[AllDaysRank]/7)*7))
set [Last4Set0] as TopCount(Filter([Report Date].[Report Date].[Day].Members,[Measures].[WeekDay]=0),4,[Measures].[AllDaysRank])
set [Last4Set1] as TopCount(Filter([Report Date].[Report Date].[Day].Members,[Measures].[WeekDay]=1),4,[Measures].[AllDaysRank])
set [Last4Set2] as TopCount(Filter([Report Date].[Report Date].[Day].Members,[Measures].[WeekDay]=2),4,[Measures].[AllDaysRank])
set [Last4Set3] as TopCount(Filter([Report Date].[Report Date].[Day].Members,[Measures].[WeekDay]=3),4,[Measures].[AllDaysRank])
set [Last4Set4] as TopCount(Filter([Report Date].[Report Date].[Day].Members,[Measures].[WeekDay]=4),4,[Measures].[AllDaysRank])
set [Last4Set5] as TopCount(Filter([Report Date].[Report Date].[Day].Members,[Measures].[WeekDay]=5),4,[Measures].[AllDaysRank])
set [Last4Set6] as TopCount(Filter([Report Date].[Report Date].[Day].Members,[Measures].[WeekDay]=6),4,[Measures].[AllDaysRank])
member [Measures].[Last4Measure] as
case [Measures].[WeekDay]
when 0 then sum([Last4Set0],[Measures].[Count])
when 1 then sum([Last4Set1],[Measures].[Count])
when 2 then sum([Last4Set2],[Measures].[Count])
when 3 then sum([Last4Set3],[Measures].[Count])
when 4 then sum([Last4Set4],[Measures].[Count])
when 5 then sum([Last4Set5],[Measures].[Count])
when 6 then sum([Last4Set6],[Measures].[Count])
end
select {[Measures].[Count],[Measures].[AllDaysRank],[Measures].[WeekDay],[Measures].[Last4Measure]} on 0
,[Report Date].[Report Date].[Day].Members on 1
from [DATA]
Result (Count, AllDaysRank, WeekDay, Last4Measure):
20151001 10 740 5 35
20151002 10 741 6 39
20151003 8 742 0 37
20151004 12 743 1 42
20151005 13 744 2 42
20151006 12 745 3 39
20151007 10 746 4 36
20151008 8 747 5 35
20151009 6 748 6 39
20151010 11 749 0 37
20151011 10 750 1 42
20151012 7 751 2 42
20151013 8 752 3 39
20151014 6 753 4 36
20151015 9 754 5 35
20151016 11 755 6 39
20151017 11 756 0 37
20151018 10 757 1 42
20151019 14 758 2 42
20151020 8 759 3 39
20151021 11 760 4 36
20151022 4 761 5 35
20151023 16 762 6 39
20151024 5 763 0 37
20151025 10 764 1 42
20151026 8 765 2 42
20151027 11 766 3 39
20151028 9 767 4 36
20151029 14 768 5 35
20151030 6 769 6 39
20151031 10 770 0 37
If you have week hierarchy or some properties (not to calculate day numbers), it would be easier.
UPDATE (weekly attribute is present):
Here is script for weeks, but please create weekday->day hierarchy first, e.g:
All
+1
-2015/01/01
-2015/01/08
...
+2
-2015/01/02
-2015/01/09
...
Code has code tricks I'll explain further:
with
member [Measures].[Week Day INFO] as [Report Date].[Week Day].Properties( "Report Date Week Day" )
member [Measures].[Last4Measure] as
/* if there are no empty 4 weeks for the first dates with data, take smaller size */
iif([Report Date].[Week Day].CurrentMember.Lag(3).Parent.Member_Key <> [Report Date].[Week Day].CurrentMember.Parent.Member_Key
,iif([Report Date].[Week Day].CurrentMember.Lag(2).Parent.Member_Key <> [Report Date].[Week Day].CurrentMember.Parent.Member_Key
,iif([Report Date].[Week Day].CurrentMember.Lag(1).Parent.Member_Key <> [Report Date].[Week Day].CurrentMember.Parent.Member_Key
,sum({[Report Date].[Week Day].CurrentMember},[Measures].[Count])
,sum({[Report Date].[Week Day].CurrentMember.Lag(1):[Report Date].[Week Day].CurrentMember},[Measures].[Count]))
,sum({[Report Date].[Week Day].CurrentMember.Lag(2):[Report Date].[Week Day].CurrentMember},[Measures].[Count]))
/* end of fixing, which could be necessary */
/* calculation part */
,sum({[Report Date].[Week Day].CurrentMember.Lag(3):[Report Date].[Week Day].CurrentMember},[Measures].[Count]))
select
{[Measures].[Count],[Measures].[Week Day INFO],[Measures].[Last4Measure]} on 0
,[Report Date].[Report Date].[Day].members on 1
from [DATA]
Week Day INFO measure is for result viewing only, not necessary in calculations.
Exact code to calculate is really simple: sum({[Report Date].[Week Day].CurrentMember.Lag(3):[Report Date].[Week Day].CurrentMember},[Measures].[Count]))
But it's possible, that you don't have empty or senseless days, which is necessary for this calculation! Since it uses .lag(3), and once we try to calculate for the VERY first, second or third weeks, it will take last members from the previous weekday, e.g. to calculate .lag(3) for the Second Wednesday ever (at the beginning of your Date dimension), it will take 2nd Wed, 1st Wed, Last Tue, Pre-last Tue, which is unacceptable, so I've added decreasing lag-level by checking Parent name (since Parent is WeekDay number from the hierarchy we've already created).
Sure thing, you'll use AVG instead of SUM. I used SUM to simplify checking an answer. It's dynamical, not for the very last member only. It depends on current member.
If you have a hierarchy within the date dimension that indicates Day of the Week then you should use it in the sort of circumstance of this question.
Via AdvWrks I wrote the following:
WITH
MEMBER [Measures].[Avg4wkDays] AS
Sum
(
Tail
( --<<find just the past 4
Exists
( --<< find all the days from the past 25 days which have the same day of the week as the current date
Tail
( --<< find the last 25 days prior to each date
NULL : [Date].[Calendar].CurrentMember
,25
)
,Exists
( --<< find the Day of the Week for the currentmember
[Date].[Day of Week].[Day of Week].MEMBERS
,[Date].[Calendar].CurrentMember
)
)
,4
)
,[Measures].[Internet Sales Amount]
)
SELECT
{
[Measures].[Internet Sales Amount]
,[Measures].[Avg4wkDays]
} ON 0
,
[Date].[Calendar].[Date] * [Date].[Day of Week].[Day of Week] ON 1
FROM [Adventure Works]
WHERE
[Date].[Calendar Year].&[2007];
It gives the following which agrees with the requirements:

Oracle SQL weeks sales SUM

I have the sales data in terms of week:
ITEM LOC WEEK SALES
111 39 16/05/2015 10
222 39 16/05/2015 23
111 39 09/05/2015 13
222 39 09/05/2015 33
I want the sum of SALES column for the last 4 weeks.
So it comes like:
ITEM LOC 4-WEEKS-SALES
111 39 23
222 39 56
Just filter for last four weeks and agregate:
select ITEM, LOC,sum(SALES)
from theTable
where WEEK > SYSDATE - ( 7 * 4 )
group by ITEM,LOC
Try to this
select ITEM,LOC,sum(SALES) '4-WEEKS-SALES'
from tablename
where Datepart(wk, WEEK)>=(Datepart(wk, Getdate())-4)
Group by ITEM,LOC,Datepart(wk, WEEK)