As perhaps not the most effective, but at least a simple and simple solution, I would do the following:
1) expand the ranges;
2) join extended ranges;
3) group the results.
This, of course, assumes that only dates are used (i.e. the 00:00 time part for all StartDate and EndDate in both tables).
To extend date ranges, I prefer to use the numbers table, for example:
SELECT m.MemberID, m.PCP, Date = DATEADD(DAY, n.Number, m.StartDate) FROM MemberPCP m INNER JOIN Numbers n ON n.Number BETWEEN 0 AND DATEDIFF(DAY, m.StartDate, m.EndDate)
And similarly for MemberPlans .
To create a combined rowset, I would use a FULL JOIN , although if you know in advance that both tables span exactly the same period of time, INNER JOIN will do the same:
SELECT * FROM MemberPCPExpanded pcp FULL JOIN MemberPlansExpanded plans ON pcp.MemberID = plans.MemberID AND pcp.Date = plans.Date
Now you only need to group the resulting rows and find the minimum and maximum dates for each combination (MemberID, PCP, PlanID) :
SELECT MemberID = ISNULL(pcp.MemberID, plans.MemberID),, pcp.PCP, plans.PlanID, StartDate = MIN(ISNULL(pcp.Date, plans.Date)), EndDate = MAX(ISNULL(pcp.Date, plans.Date)) FROM MemberPCPExpanded pcp FULL JOIN MemberPlansExpanded plans ON pcp.MemberID = plans.MemberID AND pcp.Date = plans.Date GROUP BY ISNULL(pcp.MemberID, plans.MemberID), pcp.PCP, plans.PlanID
Please note that if you use INNER JOIN instead of FULL JOIN , you do not need all these ISNULL() expressions, just select a table column, for example. pcp.MemberID instead of ISNULL(pcp.MemberID, plans.MemberID) and pcp.Date instead of ISNULL(pcp.Date, plans.Date) .
A full query might look like this:
WITH MemberPCPExpanded AS ( SELECT m.MemberID, m.PCP, Date = DATEADD(DAY, n.Number, m.StartDate) FROM MemberPCP m INNER JOIN Numbers n ON n.Number BETWEEN 0 AND DATEDIFF(DAY, m.StartDate, m.EndDate) ), MemberPlansExpanded AS ( SELECT m.MemberID, m.PlanID, Date = DATEADD(DAY, n.Number, m.StartDate) FROM MemberPlans m INNER JOIN Numbers n ON n.Number BETWEEN 0 AND DATEDIFF(DAY, m.StartDate, m.EndDate) ) SELECT MemberID = ISNULL(pcp.MemberID, plans.MemberID), pcp.PCP, plans.PlanID, StartDate = MIN(ISNULL(pcp.Date, plans.Date)), EndDate = MAX(ISNULL(pcp.Date, plans.Date)) FROM MemberPCPExpanded pcp FULL JOIN MemberPlansExpanded plans ON pcp.MemberID = plans.MemberID AND pcp.Date = plans.Date GROUP BY ISNULL(pcp.MemberID, plans.MemberID), pcp.PCP, plans.PlanID ORDER BY MemberID, StartDate
You can try this query in SQL Fiddle .