Reputation: 817
I have a Rep table with the following fields:
There can be changes to the RepNbr. I need to write a query that shows what the repnbr was for each effectivedate. What the repnbr was prior and then when there's a change. So, I'm trying to pull the repnbr of M258 on 10/21 (what the repnbr was prior), the repnbr of DM25 on 6/3/16 and what the repnbr of M258 was on 6/8/16.
I tried the following query: This query only pulls the effectivedate of 6/3 and 6/8 and doesn't look back to what the repnbr was previously.
;with t1 as
(
select
acctnbr,
repnbr,
effectivedate,
rn = row_number() over (partition by repnbr order by acctnbr)
from
reptable
where
acctnbr = '123'
)
select
*
from
t1
where
rn = '1'
order by
effectivedate
Results:
My output should look like:
What am I doing wrong with my query? Thanks,
Upvotes: 0
Views: 1076
Reputation: 14341
USE LAG()
and or LEAD()
functions for SQL 2012+
DECLARE @Rep AS TABLE (Acct INt, RepNbr CHAR(4), EffectiveDate DATETIME)
INSERT INTO @Rep VALUES
(123,'M258','2015-10-15')
,(123,'M258','2015-10-21')
,(123,'DM25','2015-06-03')
,(123,'M258','2015-06-08')
;WITH cte AS (
SELECT *
,LAG(RepNbr) OVER (PARTITION BY Acct ORDER BY EffectiveDate) as PrevRepNbr
FROM
@Rep
)
SELECT Acct, RepNbr, EffectiveDate
FROM
cte
WHERE
PrevRepNbr IS NULL
OR PrevRepNbr <> RepNbr
Note though that your example isn't in order of Effective Date so your results will not be as you described. Because 10-21 is after 6-3...
Acct RepNbr EffectiveDate
123 DM25 2015-06-03 00:00:00.000
123 M258 2015-06-08 00:00:00.000
123 M258 2015-10-15 00:00:00.000
123 M258 2015-10-21 00:00:00.000
So that would mean that the RepNbr only changes on 6/8 from DM25 to M258
If you change your example table to:
DECLARE @Rep AS TABLE (Acct INt, RepNbr CHAR(4), EffectiveDate DATETIME)
INSERT INTO @Rep VALUES
(123,'M258','2015-06-03')
,(123,'M258','2015-06-08')
,(123,'DM25','2015-10-15')
,(123,'M258','2015-10-21')
Then it woudl start with M258 on 6/3 change to DM25 on 10/15 and then change back to M258 on 10/21.
If you don't want to see the original/starting value just remove the WHERE PrevRepNbr IS NULL
Edit without @Rep:
;WITH cte AS (
SELECT
Acct
,RepNbr
,EffectiveDate
,LAG(RepNbr) OVER (PARTITION BY Acct ORDER BY EffectiveDate) as PrevRepNbr
FROM
TableName
)
SELECT Acct, RepNbr, EffectiveDate
FROM
cte
WHERE
PrevRepNbr IS NULL
OR PrevRepNbr <> RepNbr
Upvotes: 2
Reputation: 22811
Older Sql sever versions grouping
DECLARE @Rep AS TABLE (Acctnbr int, RepNbr CHAR(4), EffectiveDate DATETIME)
INSERT INTO @Rep VALUES
(123,'M258','2015-10-15')
,(123,'M258','2015-10-21')
,(123,'DM25','2015-06-08')
,(123,'M258','2015-06-03');
WITH cte AS (
select *,
grp = row_number() over(partition by acctnbr order by effectivedate)
- row_number() over(partition by acctnbr, RepNbr order by effectivedate)
from @rep
)
SELECT acctnbr, RepNbr, max(effectivedate) effectivedate
from cte
group by acctnbr, RepNbr, grp
order by acctnbr, max(effectivedate) desc;
Upvotes: 2