Reputation: 327
I'm using SQL Server 2018 and I have a single table called SALES, which looks something like this
SALES_PERSON_ID MONTH SALES
001 Aug-20 3
002 Aug-20 2
003 Aug-20 0
001 Sep-20 4
002 Sep-20 2
003 Sep-20 3
Each new month is added to the table, which will show the accumulative sales for each sales person.
I want to summarise this data as sales this month vs last month, which I've done like this:
SELECT
tb1.SALES_PERSON_ID
,SALES_THIS_MONTH
,SALES_LAST_MONTH
FROM
(SELECT SALES_PERSON_ID, MONTH, SUM(SALES) AS SALES_THIS_MONTH
FROM SALES
WHERE MONTH = 'Sep-20') AS tb1
JOIN
(SELECT SALES_PERSON_ID, MONTH, SUM(SALES) AS SALES_LAST_MONTH
FROM SALES
WHERE MONTH = 'Aug-20') AS tb2
ON. tb1.SALES_PERSON_ID = tb2.SALES_PERSON_ID
If Sep-20 is the current month, then it gives me something like this:
SALES_PERSON_ID SALES_THIS_MONTH SALES_LAST_MONTH
001 4 3
002 2 2
003 3 0
That works fine, but in reality I have hundreds of thousands of records with hundreds of months and I can't "hard-code" the dates for all possible months in a WHERE clause. I want a dynamic solution that will always provide the sum of sales for a given month and what the sum of sales was for the previous month specific to that record.
So I would need my tb2 to somehow always know which month tb1 was referring to and then subtract a month. Any help would be appreciated!
Upvotes: 1
Views: 1834
Reputation: 1269623
Use lag()
:
select s.*,
lag(sales) over (partition by SALES_PERSON_ID order by month) as prev_sales
from sales s;
This assumes that month
is really a date
. If it is not, you can use:
lag(sales) over (partition by SALES_PERSON_ID order by convert(date, '01-' + month)) as prev_sales
If you want to filter this for only the most recent month, use a subquery for the lag()
:
select s.*
from (select s.*,
lag(sales) over (partition by SALES_PERSON_ID order by month) as prev_sales
from sales s
) s
where s.month = dateadd(day, 1, eomonth(getdate(), -1))
Upvotes: 1