Reputation: 61
I have the following table for example. I would like to calculate the changes increase or decrease from previous month. This will show a percentage of change from previous month.
Location Month Sales A Jan 1753 B Jan 32130 C Jan 71353 D Jan 74885 E Jan 50241 F Jan 66393 A Feb 80633 B Feb 67918 C Feb 73330 D Feb 33269 E Feb 78915 F Feb 98817 A Mar 80633 B Mar 67918 C Mar 73330 D Mar 33269 E Mar 78915 F Mar 98817
I wan to create a table like following. I searched stack overflow but was not able to get table.
Location Selected Current_Month Prvisous_Month Change A Feb 80633 1753 4500% B Feb 67918 32130 111% C Feb 73330 71353 3% D Feb 33269 74885 -56% E Feb 78915 50241 57% F Feb 98817 66393 49%
Upvotes: 0
Views: 159
Reputation: 10701
Assuming that you change the Month
attribute to date then you can use a LAG
window function easily like this
SELECT location,
month,
sales,
lag(sales) over (order by month) previous,
(sales/lag(sales) over (order by month) - 1) * 100 as change
FROM your_table
WHERE month = 'feb'
The major issue now in your task is the correct ordering of Month
which would be much more easier with date, or numbers.
EDIT: You can use the ordering solution of Cool_Br33ze for current data:
SELECT location,
month,
sales,
lag(sales) over (order by MONTH([T].[Month] + ' 1 1900')) previous, -- taken from Cool_Br33ze solution
(sales/lag(sales) over (order by MONTH([T].[Month] + ' 1 1900')) - 1) * 100 as change
FROM your_table
WHERE month = 'feb'
However, the best option is to change the data type of Month
...
Upvotes: 0
Reputation: 514
SELECT A.Location, 'Feb' AS Selected, A.Sales AS Current_Month
, B.Sales AS Prvisous_Month, (A.Sales - B.Sales)/ B.Sales AS Change
FROM YourTable A JOIN YourTable B
ON A.Month = B.Month + 1 -- You will have to represent Months by numbers
WHERE A.Month = 2 -- Selected month
Upvotes: 0
Reputation: 3837
If you can't change the datatype of the "Month" column, for whatever reason, then this solution may work
DECLARE @Table TABLE ([Location] CHAR(1), [Month] NVARCHAR(3), Sales INT )
INSERT INTO @Table
([Location], [Month], Sales)
VALUES
('A',N'Jan',1753),
('B',N'Jan',32130),
('C',N'Jan',71353),
('D',N'Jan',74885),
('E',N'Jan',50241),
('F',N'Jan',66393),
('A',N'Feb',80633),
('B',N'Feb',67918),
('C',N'Feb',73330),
('D',N'Feb',33269),
('E',N'Feb',78915),
('F',N'Feb',98817),
('A',N'Mar',80633),
('B',N'Mar',67918),
('C',N'Mar',73330),
('D',N'Mar',33269),
('E',N'Mar',78915),
('F',N'Mar',98817)
DECLARE @Selection NVARCHAR(3) = N'Feb' -- Enter Selected Month here
;WITH cteX
AS(
SELECT
T.[Location]
, T.[Month]
, MonthNum = MONTH([T].[Month] + ' 1 1900') --Use some dummy date here
, T.Sales
FROM @Table T
)
SELECT
T.[Location]
, Selected = T.Month
, CurrentMonth = T.Sales
, PreviousMonth = T1.Sales
, Change = CAST((T.Sales - T1.Sales) / (T1.Sales * 1.0) * 100.0 AS DECIMAL)
FROM cteX T
INNER JOIN
cteX T1 ON T1.MonthNum = T.MonthNum - 1
AND T1.[Location] = T.[Location]
WHERE
T.[Month] = @Selection
Output
Upvotes: 1
Reputation: 62
Something like this should be a good start. As Cool_Br33ze noted, you should rethink the date column of this table.
SELECT
*,
referenceTimePeriod / NULLIF(comparisonTimePeriod, 0) -- avoid DIV0 errors
FROM (
SELECT Location, Sales
FROM myTable
WHERE month = 'jan'
) AS referenceTimePeriod
FULL JOIN(
SELECT Location, Sales
FROM myTable
WHERE month = 'feb'
) AS comparisonTimePeriod ON referenceTimePeriod.Location = comparisonTimePeriod .Location
Upvotes: 0