I want to show all profit centers a user had. The necessary information are in two tables.
- TerritoryAssignment
+-------------0----------+------------+------------+--------------+
| TerritoryID | DBUserID | ValidFrom | ValidThru | AssignmentID |
+-------------+----------+------------+------------+--------------+
| T1 | 472 | 2019-03-01 | 2019-12-31 | 1389 |
| T4 | 472 | 2020-01-01 | 2020-10-31 | 2105 |
| T8 | 472 | 2020-11-01 | 2021-09-12 | 2226 |
| T12 | 472 | 2021-09-13 | 2021-11-30 | 2578 |
| T2 | 472 | 2021-12-01 | 9999-12-31 | 2659 |
+-------------+----------+------------+------------+--------------+
- TerritoryDetails
+-----------+--------------+------------+------------+--------------------+
TerritoryID | ProfitCenter | ValidFrom | ValidThru | TerritoryDetailsID |
+-----------+--------------+------------+------------+--------------------+
| T2 | P05 | 2021-12-01 | 2022-04-30 | 983 |
| T2 | P18 | 2022-05-01 | 9999-12-31 | 1029 |
| T1 | P45 | 2012-09-01 | 9999-12-31 | 502 |
| T4 | P23 | 2020-01-01 | 9999-12-31 | 755 |
| T12 | P05 | 2020-01-01 | 9999-12-31 | 846 |
| T8 | P18 | 2020-01-01 | 9999-12-31 | 956 |
+-----------+--------------+------------+------------+--------------------+
Both tables are joined over the field TerritoryID.
As you can see, the user hat profit center P18 at two different time periods. Therefore a simple MIN and MAX with grouping is not possible. Also see that there are two records for profit center P05 which should be aggregated into one.
I want to get all Profit Centers a user had in the past including the exact start date and end date. The output could look like this:
+----------+------------+------------+--------------+
| DBUserID | ValidFrom | ValidThru | ProfitCenter |
+----------+------------+------------+--------------+
| 472 | 2019-03-01 | 2019-12-31 | P45 |
| 472 | 2020-01-01 | 2020-10-31 | P23 |
| 472 | 2020-11-01 | 2021-09-12 | P18 |
| 472 | 2021-09-13 | 2022-04-30 | P05 |
| 472 | 2022-05-01 | 9999-12-31 | P18 |
+----------+------------+------------+--------------+
The problem is:
- A user can have different territory assignments over the time -> multiple entries in table TerritoryAssignment for a user.
- Territory details can change -> multiple entries in table TerritoryDetails for a territory.
- The profit center can be the same over several TerritoryDatails records.
- The profit canter can be appear at another territory as well.
- The start and end dates in the records of both tables are independent and therefore cannot used for a join.
I already tried some CTE with ROW_NUMBER() but was not successful. Here my last try, not giving the correct result:
SELECT
DBUserID,
ProfitCenter,
MIN(ValidFrom) AS IslandStartDate,
MAX(ValidThru) AS IslandEndDate
FROM
(
SELECT
*,
CASE WHEN Groups.PreviousEndDate >= ValidFrom THEN 0 ELSE 1 END AS IslandStartInd,
SUM(CASE WHEN Groups.PreviousEndDate >= ValidFrom THEN 0 ELSE 1 END) OVER (ORDER BY Groups.RN) AS IslandId
FROM
(
SELECT
ROW_NUMBER() OVER(ORDER BY DBUserID,ProfitCenter,TD.ValidFrom,TD.ValidThru) AS RN,
DBUserID,
ProfitCenter,
IIF(TA.ValidFrom<TD.ValidFrom,TD.ValidFrom,TA.ValidFrom) AS ValidFrom,
IIF(TA.ValidThru>TD.ValidThru,TD.ValidThru,TA.ValidThru) AS ValidThru,
LAG(TD.ValidFrom,1) OVER (ORDER BY DBUserID,ProfitCenter,TD.ValidFrom,TD.ValidThru) AS PreviousEndDate
FROM
dbo.TerritoryDetails TD INNER JOIN dbo.TerritoryAssignment TA ON TD.TerritoryID=TA.TerritoryID
WHERE TA.DBUserID=472
AND (
(TD.ValidFrom<=TA.ValidFrom AND TD.ValidThru>=TA.ValidFrom)
OR (TD.ValidFrom>=TA.ValidFrom AND TD.ValidThru<=TA.ValidThru)
OR (TD.ValidFrom<=TA.ValidThru AND TD.ValidThru>=TA.ValidThru)
)
) Groups
) Islands
GROUP BY
IslandId,DBUserID,ProfitCenter
ORDER BY
IslandStartDate desc
Does anybody can help?