I have come up with a very simple example to demonstrate the problem I'm trying to solve.
I need to select customer contracts that...
1) have expired or will expire in the next three months
AND
2) that do not have a new contract already in place.
All Expired contracts remain in the table along with the new ones.
Based on these business rules my expected results from the test data would be to return contract ID 6 (customer 3) as it is an expired contract with no new contract and contract ID 7 (customer 4) as it has less than 3 months to run.
I have looked at some examples where the solution is to join the table to itself
e.g. how do I query sql for a latest record date for each user
I think I could select only the most recent contract for each customer then check its expiry date like this but it only returns Contract ID 6 and not 7 like I'm expecting. I'm using SQL 2008 R2.
Any Ideas where I'm going wrong?
SELECT [ContractID]
,[StartDate]
,[ExpiryDate]
,TC.[CustomerID]
FROM [Test].[dbo].[TestContract] TC
inner join
(
select CustomerID,
MAX(ExpiryDate) as MaxDate
From Test.dbo.TestContract
Group by CustomerID
)CM on TC.CustomerID = CM.CustomerID and TC.ExpiryDate = CM.MaxDate
Where TC.ExpiryDate < DateAdd(DAY, 30, GETDATE())
Here is my test Data
ContractID StartDate ExpiryDate CustomerID
1 2017-02-01 00:00:00.000 2018-02-01 00:00:00.000 1
2 2016-01-01 00:00:00.000 2017-01-01 00:00:00.000 1
4 2016-01-01 00:00:00.000 2017-11-01 00:00:00.000 2
5 2017-11-01 00:00:00.000 2018-11-01 00:00:00.000 2
6 2016-10-01 00:00:00.000 2017-10-01 00:00:00.000 3
7 2016-12-01 00:00:00.000 2017-12-01 00:00:00.000 4
8 2015-12-01 00:00:00.000 2016-12-01 00:00:00.000 4
9 2017-06-01 00:00:00.000 2018-06-01 00:00:00.000 5
Here is a script to recreate my test table and data.
USE [Test]
GO
/****** Object: Table [dbo].[TestContract] Script Date: 10/05/2017 17:07:33 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[TestContract](
[ContractID] [int] IDENTITY(1,1) NOT NULL,
[StartDate] [datetime] NOT NULL,
[ExpiryDate] [datetime] NOT NULL,
[CustomerID] [int] NOT NULL,
CONSTRAINT [PK_TestContract] PRIMARY KEY CLUSTERED
(
[ContractID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
SET IDENTITY_INSERT [dbo].[TestContract] ON
INSERT [dbo].[TestContract] ([ContractID], [StartDate], [ExpiryDate], [CustomerID]) VALUES (1, CAST(0x0000A70D00000000 AS DateTime), CAST(0x0000A87A00000000 AS DateTime), 1)
INSERT [dbo].[TestContract] ([ContractID], [StartDate], [ExpiryDate], [CustomerID]) VALUES (2, CAST(0x0000A58000000000 AS DateTime), CAST(0x0000A6EE00000000 AS DateTime), 1)
INSERT [dbo].[TestContract] ([ContractID], [StartDate], [ExpiryDate], [CustomerID]) VALUES (4, CAST(0x0000A58000000000 AS DateTime), CAST(0x0000A81E00000000 AS DateTime), 2)
INSERT [dbo].[TestContract] ([ContractID], [StartDate], [ExpiryDate], [CustomerID]) VALUES (5, CAST(0x0000A81E00000000 AS DateTime), CAST(0x0000A98B00000000 AS DateTime), 2)
INSERT [dbo].[TestContract] ([ContractID], [StartDate], [ExpiryDate], [CustomerID]) VALUES (6, CAST(0x0000A69200000000 AS DateTime), CAST(0x0000A7FF00000000 AS DateTime), 3)
INSERT [dbo].[TestContract] ([ContractID], [StartDate], [ExpiryDate], [CustomerID]) VALUES (7, CAST(0x0000A6CF00000000 AS DateTime), CAST(0x0000A83C00000000 AS DateTime), 4)
INSERT [dbo].[TestContract] ([ContractID], [StartDate], [ExpiryDate], [CustomerID]) VALUES (8, CAST(0x0000A56100000000 AS DateTime), CAST(0x0000A6CF00000000 AS DateTime), 4)
INSERT [dbo].[TestContract] ([ContractID], [StartDate], [ExpiryDate], [CustomerID]) VALUES (9, CAST(0x0000A78500000000 AS DateTime), CAST(0x0000A8F200000000 AS DateTime), 5)
SET IDENTITY_INSERT [dbo].[TestContract] OFF