BEGIN TRAN--Sample dataCREATE TABLE Customer (customerID INT IDENTITY PRIMARY KEY, Name VARCHAR(20))INSERT INTO CustomerSELECT 'Me'UNION ALL SELECT 'Myself'UNION ALL SELECT 'Irene'--Sample dataCREATE TABLE Addresses (addressesID INT IDENTITY PRIMARY KEY, customerID INT, addressLine1 VARCHAR(20), activeFrom DATE, activeTo DATE)INSERT INTO AddressesSELECT 1, '1 Short Street', '2000-01-01', '2005-12-31'UNION ALL SELECT 2, '100000 Long Street', '1985-01-26', NULLUNION ALL SELECT 3, '2 Short Street', '2005-12-30', NULLUNION ALL SELECT 1, '3 Short Street', '2006-01-01', NULL--Sample dataCREATE TABLE EmailAddresses (emailAddressesID INT IDENTITY PRIMARY KEY, customerID INT, emailAddress VARCHAR(100), activeFrom DATE, activeTo DATE)INSERT INTO EmailAddressesSELECT 1, 'Me.2k@hotmail.com', '2000-01-01', '2011-12-31'UNION ALL SELECT 1, 'hotmaillSucks.Me.2k12@gmail.com', '2012-01-01', NULL--Required to get the dates from and toSELECT CONVERT(DATE,DATEADD(DAY,N,'1901-01-01')) AS NINTO TallyFROM (SELECT TOP 1000000 ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) AS N FROM master.dbo.syscolumns sc1, master.dbo.syscolumns sc2, master.dbo.syscolumns sc3) aALTER TABLE TallyALTER COLUMN N DATE NOT NULLALTER TABLE TallyADD CONSTRAINT PK_Tally_N PRIMARY KEY CLUSTERED (N) WITH FILLFACTOR = 100--Actual querySELECT cust.customerID, cust.Name, times.activeFrom, times.activeTo,times.addressLine1, times.emailAddressFROM Customer custLEFT OUTER JOIN (SELECT addresses.customerID, MAX(CASE WHEN ISNULL(addresses.activeFrom,GETDATE()) >= ISNULL(emails.activeFrom,GETDATE()) THEN addresses.activeFrom ELSE ISNULL(emails.activeFrom,addresses.activeFrom) END) AS activeFrom, MAX(CASE WHEN ISNULL(addresses.activeTo,GETDATE()) <= ISNULL(emails.activeTo,GETDATE()) THEN addresses.activeTo ELSE emails.activeTo END) AS activeTo, addresses.addressLine1, emails.emailAddress FROM (SELECT addressesID, customerID, addressLine1, activeFrom, activeTo, N FROM Addresses CROSS APPLY Tally WHERE activeFrom <= N AND (ISNULL(activeTo,GETDATE()) >= N)) addresses LEFT OUTER JOIN (SELECT emailAddressesID, customerID, emailAddress, activeFrom, activeTo, N FROM EmailAddresses CROSS APPLY Tally WHERE activeFrom <= N AND (ISNULL(activeTo,GETDATE()) >= N)) emails ON addresses.N = emails.N AND addresses.customerID = emails.customerID GROUP BY addresses.addressLine1, emails.emailAddress, addresses.customerID) times ON cust.customerID = times.customerIDROLLBACK
DECLARE @Customer TABLE ( CustomerID integer PRIMARY KEY)DECLARE @Address TABLE( AddressID integer PRIMARY KEY NONCLUSTERED, CustomerID integer NOT NULL, FromDate date NOT NULL, ToDate date NOT NULL, UNIQUE CLUSTERED (CustomerID, AddressID))DECLARE @Email TABLE ( EmailID int PRIMARY KEY NONCLUSTERED, CustomerID integer NOT NULL, FromDate date NOT NULL, ToDate date NOT NULL, UNIQUE CLUSTERED (CustomerID, EmailID))
INSERT @Customer (CustomerID)VALUES (1)INSERT @Address (AddressID, CustomerID, FromDate, ToDate)VALUES (1, 1, '2000-01-01', '2005-12-31'), (2, 1, '2006-01-01', '9999-12-31')INSERT @Email (EmailID, CustomerID, FromDate, ToDate)VALUES (1, 1, '2000-01-01', '2005-12-31'), (2, 1, '2006-01-01', '2011-12-31'), (3, 1, '2012-01-01', '9999-12-31')
SELECT T1.CustomerID, T1.AddressID, T1.EmailID, T1.FromDate, T1.ToDateFROM ( SELECT c.CustomerID, a.AddressID, e.EmailID, (SELECT MAX(U.FromDate) FROM (VALUES (a.FromDate), (e.FromDate)) AS U (FromDate)) AS FromDate, (SELECT MIN(U.ToDate) FROM (VALUES (a.ToDate), (e.ToDate)) AS U (ToDate)) AS ToDate FROM @Customer AS c LEFT JOIN @Address AS a ON a.CustomerID = c.CustomerID LEFT JOIN @Email AS e ON e.CustomerID = c.CustomerID) AS T1WHERE T1.FromDate <= T1.ToDate