客人所有帐户的最短日期

Min date for a guest across all their accounts

所以让我先解释一下我们的设置。我们正在查看的 SQL Server 2012 上有两个 table:

PL_Guest and PL_MergedGuests

PL_Guest结构如下:

Create Table PL_Guest(
GuestID [int] IDENTITY(1,1) NOT NULL Primary Key,
CreatedDate [date] NOT NULL)

PL_MergedGuests结构如下:

Create Table PL_MergedGuests(
MergeID [int] IDENTITY(1,1) NOT NULL Primary Key,
VictimID [int] NOT NULL,
SurvivorID [int] NOT NULL)

所以情况是这样的:

PL_Guesttable 记录了每一个曾经创建的客人,并且从来没有从中删除任何记录。 PL_MergedGuests table 包含我们合并两个帐户时的 victimid 和 survivorid 列表。例如,如果一个人由于某种原因获得了多个 Guestid 分配给他们,我们会这样做。现在,当合并完成后,前线员工只需选择该人将保留的多个帐户中的哪一个,这通常是根据客人手头的卡来完成的,以便为客人减少更改。如果访客的 GuestID 为 5,创建日期为 1/1/2013,GuestID 为 10,创建日期为 10/1/2015;合并完成后,GuestID 5 被合并到 GuestID 10 中,然后 GuestID 5 成为受害者,而 GuestID 10 成为幸存者。当我们 运行 报告时,我们只查看幸存者账户。但是,我们被要求为每位客人找到最早的创建日期。因此,对于上面的示例,他们希望输入 returns GuestID 10 创建日期 1/1/2013,因为具有 GuestID 10 的访客也有 GuestID 5,其较早的创建日期为 1/1/2013。

现在真正困难的部分是,一个来宾可以被合并的次数没有限制,而且这些 table 每个都拥有超过 1 亿条记录。我在想这将需要某种循环(我认为这可能指的是递归编码,尽管我对此不确定)但我不知道如何编写该代码。我确实有权创建新的 tables,如果这有帮助但不能修改当前的 tables。

由于缺少 "real" 个示例,我自己定义了几个示例并维护了几个合并。我使用递归 cte 来评估所需的 "min creation date"。我不知道这在您的桌子上的工作速度有多快或多慢,但至少它应该为进一步开发提供一个可用的起点:

DECLARE @PL_Guest TABLE(
  GuestID INT NOT NULL,
  CreatedDate [date] NOT NULL
)

DECLARE @PL_MergedGuests TABLE(
  MergeID  INT NOT NULL,
  VictimID [int] NOT NULL,
  SurvivorID [int] NOT NULL
)


INSERT INTO @PL_Guest
  VALUES (1, '2016-11-01'), (2, '2016-12-01'), (3, '2016-11-01'), (4, '2016-12-01'), (5, '2017-01-01'), (6, '2017-01-01'), (7, '2017-02-01'), (8, '2017-02-01'), (9, '2017-03-01'), (10, '2017-04-01');

INSERT INTO @PL_MergedGuests
  VALUES (1, 3, 4), (2, 4, 6), (3, 9, 6), (4, 10, 2), (5, 8, 5); 

WITH cteRecursice AS(
  SELECT mg1.SurvivorID, mg1.VictimID, 1 AS lvl, mg1.SurvivorID AS LastSurvivor, pg1.CreatedDate AS LastSurvivorCreatedDate
    FROM @PL_MergedGuests mg1
    JOIN @PL_Guest pg1 ON pg1.GuestID = mg1.SurvivorID
  UNION ALL
  SELECT mg2.SurvivorID, mg2.VictimID, c.lvl + 1 AS lvl, c.LastSurvivor, c.LastSurvivorCreatedDate
    FROM @PL_MergedGuests mg2
    JOIN cteRecursice c ON mg2.SurvivorID = c.VictimID
),
cteGrouped AS(
  SELECT LastSurvivor, LastSurvivorCreatedDate, MIN(CreatedDate) AS MinCreatedDate
    FROM cteRecursice
    JOIN @PL_Guest AS pg ON pg.GuestID = VictimID
    WHERE LastSurvivor NOT IN (SELECT VictimID FROM @PL_MergedGuests AS pmg)
    GROUP BY LastSurvivor, LastSurvivorCreatedDate
  UNION ALL
  SELECT GuestID, CreatedDate, CreatedDate
    FROM @PL_Guest pg
    WHERE GuestID NOT IN (SELECT VictimID FROM @PL_MergedGuests UNION ALL SELECT SurvivorID FROM @PL_MergedGuests)
)
SELECT LastSurvivor, IIF(MinCreatedDate < LastSurvivorCreatedDate, MinCreatedDate, LastSurvivorCreatedDate) AS MinCreatedDate
  FROM cteGrouped cg
  ORDER BY LastSurvivor
  OPTION (MAXRECURSION 0)