Since you want to know when the name changes, the only way that I can think of it so match each row with it's subsequent row. To accomplish this, I would assign a row number to each row, ordered by date so that your data would look like this.
Code:
Date Name RowId
20160201 A 1
20160301 A 2
20160501 A 3
20160801 B 4
20161201 B 5
I'm going to show some code. Please bear in mind that I am create a table variable so that I can dummy up your data. Obviously, in your actual solution, you wouldn't want to use the table variable.
Code:
Declare @Temp Table(Date Int, Name VarChar(10));
Insert Into @Temp Values(20160201,'A')
Insert Into @Temp Values(20160301,'A')
Insert Into @Temp Values(20160501,'A')
Insert Into @Temp Values(20160801,'B')
Insert Into @Temp Values(20161201,'B')
Select *,
Row_Number() Over (Order By Date) As RowId
From @Temp
When you run the code above, you will see that it generates the data with an incrementing RowId. This is important because now we can join the table back to itself based on the row id, like this....
Code:
Declare @Temp Table(Date Int, Name VarChar(10));
Insert Into @Temp Values(20160201,'A')
Insert Into @Temp Values(20160301,'A')
Insert Into @Temp Values(20160501,'A')
Insert Into @Temp Values(20160801,'B')
Insert Into @Temp Values(20161201,'B')
; With Data As
(
Select *,
Row_Number() Over (Order By Date) As RowId
From @Temp
)
Select *
From Data As Before
Inner Join Data As After
On Before.RowId = After.RowId - 1
When you run the code above, you'll get results like this...
Code:
Date Name RowId Date Name RowId
----------- ---------- -------------------- ----------- ---------- --------------------
20160201 A 1 20160301 A 2
20160301 A 2 20160501 A 3
20160501 A 3 20160801 B 4
20160801 B 4 20161201 B 5
Note that the first 3 columns are from the "before" table and the last 3 rows are from the "After" table.
The data you want would be from the 3rd row where a.name <> b.name. Specifically, you want the date and name from the after table.
Now all we have to do is to add a where clause and restrict the columns returned. Like this:
Code:
Declare @Temp Table(Date Int, Name VarChar(10));
Insert Into @Temp Values(20160201,'A')
Insert Into @Temp Values(20160301,'A')
Insert Into @Temp Values(20160501,'A')
Insert Into @Temp Values(20160801,'B')
Insert Into @Temp Values(20161201,'B')
; With Data As
(
Select *,
Row_Number() Over (Order By Date) As RowId
From @Temp
)
Select After.Date,
After.Name
From Data As Before
Inner Join Data As After
On Before.RowId = After.RowId - 1
Where Before.Name <> After.Name
When you run the code above, you'll see that you get exactly what you asked for in your original question.
Please note that this code will only work if the name only changes 1 time. If the name changes multiple times, you will get the date and new name for each time the name is changed. If you want to return only the last time the name is changed, then you could do this.
Code:
Declare @Temp Table(Date Int, Name VarChar(10));
Insert Into @Temp Values(20160201,'A')
Insert Into @Temp Values(20160301,'A')
Insert Into @Temp Values(20160501,'A')
Insert Into @Temp Values(20160801,'B')
Insert Into @Temp Values(20161201,'B')
Insert Into @Temp Values(20161202,'C')
Insert Into @Temp Values(20170101,'C')
; With Data As
(
Select *,
Row_Number() Over (Order By Date) As RowId
From @Temp
)
Select [!]Top 1 [/!]After.Date,
After.Name
From Data As Before
Inner Join Data As After
On Before.RowId = After.RowId - 1
Where Before.Name <> After.Name
[!]Order By Date DESC[/!]
-George
Microsoft SQL Server MVP
My Blogs
SQLCop
twitter
"The great things about standards is that there are so many to choose from." - Fortune Cookie Wisdom