1

对这个查询和一些提示/建议感到有点头疼,我们将不胜感激。我找不到与我的问题真正相关的任何东西 - 我在传递闭包上发现了一些东西,这不是我所需要的,因为我的数据可能会创建一个循环/循环,我认为这会导致递归调用无限循环.

假设我有两个基本表格,其下方显示数据。完全披露:Memberships表是一个 CTE,它已经做了相当多的逻辑来计算CServiceDate列的值。Transfers表是一个实际的表,除了 PK 和FromMembershipIDToMembershipID关系之外不包含很多 内容。

会员资格

 
+==========+===============+================+====== =========+
| 个人ID | 会员ID | 会员日期 | 服务日期 |
+==========+===============+================+====== =========+
| 1 | 15 | 2016 年 8 月 1 日 | 2017 年 8 月 27 日 |
+----------+--------------+----------------+------ --------+
| 1 | 16 | 2016 年 3 月 25 日 | 2000 年 9 月 1 日 |
+----------+--------------+----------------+------ --------+
| 1 | 17 | 2011 年 12 月 6 日 | 1995 年 5 月 15 日 |
+----------+--------------+----------------+------ --------+
| 1 | 18 | 2009 年 1 月 12 日 | 1998 年 2 月 28 日 |
+----------+--------------+----------------+------ --------+
| 1 | 19 | 2016 年 4 月 8 日 | 1994 年 7 月 10 日 |
+----------+--------------+----------------+------ --------+
| 1 | 20 | 2010 年 6 月 11 日 | 1997 年 11 月 12 日 |
+----------+--------------+----------------+------ --------+

转移

+=====+====================+================+
| 时间 | FromMembershipID | ToMembershipID |
+=====+====================+================+
| 1 | 16 | 15 |
+-----+------------------+----------------+
| 2 | 18 | 17 |
+-----+------------------+----------------+
| 3 | 19 | 17 |
+-----+------------------+----------------+
| 4 | 20 | 18 |
+-----+------------------+----------------+
| 5 | 20 | 19 |
+-----+------------------+----------------+

问题 我需要从查询中获取 Memberships CTE 中的每一行(即每个 MembershipID),我想返回所有相关 MembershipID 的 MIN CServiceDate。我将此 MIN 值称为 ECSD(预期信用服务日期)。ECSD的计算只有两个条件:

  • 如果通过查看 FromMembershipID 和 ToMembershipID 列,通过Transfers表以某种方式将成员资格记录与当前 MembershipID 关联,则该成员资格记录被视为与当前 MembershipID“相关”。例如,对于 MembershipID 20,如果我们查看Transfers表,我们可以看到 MembershipIDs 20、19、18 和 17 都是通过传递性相关的(此外:通过Transfers表,我们可以看到 MembershipIDs 15 和 16 与彼此,但不是 [20,19,18,17] )
  • 在上面直接派生的可传递相关成员列表中,在计算 ECSD 时可在传递关系列表中考虑的唯一成员是 MembershipDate 早于当前 MembershipID 的成员。例如,基于给定 MembershipID 的 MembershipDates 和Transfers表,如果查看 MembershipID 17,则在计算 MembershiID 17 的 ECSD 时不能考虑 MembershipID 19,因为 MembershipID 19 的 MembershipDate(2016 年 4 月 8 日)不早于MembershipID 17's (Dec-06-2011)

ECSD 列的预期输出

+==========+===============+================+====== ========+==============+
| 个人ID | 会员ID | 会员日期 | 服务日期 | 教育发展署 |
+==========+===============+================+====== ========+==============+
| 1 | 15 | 2016 年 8 月 1 日 | 2017 年 8 月 27 日 | 2000 年 9 月 1 日 |
+----------+--------------+----------------+------ --------+-------------+
| 1 | 16 | 2016 年 3 月 25 日 | 2000 年 9 月 1 日 | 2000 年 9 月 1 日 |
+----------+--------------+----------------+------ --------+-------------+
| 1 | 17 | 2011 年 12 月 6 日 | 1995 年 5 月 15 日 | 1995 年 5 月 15 日 |
+----------+--------------+----------------+------ --------+-------------+
| 1 | 18 | 2009 年 1 月 12 日 | 1998 年 2 月 28 日 | 1998 年 2 月 28 日 |
+----------+--------------+----------------+------ --------+-------------+
| 1 | 19 | 2016 年 4 月 8 日 | 1994 年 7 月 10 日 | 1994 年 7 月 10 日 |
+----------+--------------+----------------+------ --------+-------------+
| 1 | 20 | 2010 年 6 月 11 日 | 1997 年 11 月 12 日 | 1997 年 11 月 12 日 |
+----------+--------------+----------------+------ --------+-------------+

请注意:

  • MembershipID 可以在 FromMembershipID 和 ToMembershipID 列中显示多次。这些列值不必是唯一的。
  • (编辑后添加)我希望将此解决方案应用于传输深度超过 2 层的较大数据集。请参阅下面的示例:

示例 2

会员资格

+==========+===============+================+====== =========+
| 人物 | 会员ID | 会员日期 | 服务日期 |
+==========+===============+================+====== =========+
| 499510 | 548426 | 2014-09-29 | 2014-09-29 |
+----------+--------------+----------------+------ --------+
| 499510 | 548428 | 2014-01-29 | 2014-01-29 |
+----------+--------------+----------------+------ --------+
| 499510 | 548425 | 2012-05-28 | 2012-05-28 |
+----------+--------------+----------------+------ --------+
| 499510 | 548429 | 2011-11-23 | 2011-11-23 |
+----------+--------------+----------------+------ --------+
| 499510 | 548427 | 2008-07-03 | 2008-07-03 |
+----------+--------------+----------------+------ --------+
| 499510 | 548431 | 2001-05-01 | 1976-01-01 |
+----------+--------------+----------------+------ --------+
| 499510 | 548430 | 1998-10-08 | 1998-10-08 |
+----------+--------------+----------------+------ --------+

转移

+=======+=========+==================+============= ===+
| 时间 | 进程号 | FromMembershipID | ToMembershipID |
+=======+=========+==================+============= ===+
| 10664 | 499510 | 548430 | 548431 |
+-------+--------+------------------+------------- ---+
| 10665 | 499510 | 548431 | 548427 |
+-------+--------+------------------+------------- ---+
| 10666 | 499510 | 548427 | 548429 |
+-------+--------+------------------+------------- ---+
| 10667 | 499510 | 548429 | 548425 |
+-------+--------+------------------+------------- ---+
| 10668 | 499510 | 548425 | 548428 |
+-------+--------+------------------+------------- ---+
| 10669 | 499510 | 548428 | 548426 |
+-------+--------+------------------+------------- ---+
| 13085 | 499510 | 548430 | 548427 |
+-------+--------+------------------+------------- ---+
| 13086 | 499510 | 548427 | 548425 |
+-------+--------+------------------+------------- ---+
| 13087 | 499510 | 548425 | 548426 |
+-------+--------+------------------+------------- ---+
| 13088 | 499510 | 548431 | 548429 |
+-------+--------+------------------+------------- ---+
| 13089 | 499510 | 548429 | 548428 |
+-------+--------+------------------+------------- ---+

预期结果

+==========+===============+================+====== ========+=============+
| 人物 | 会员ID | 会员日期 | 服务日期 | 教育发展署 |
+==========+===============+================+====== ========+=============+
| 499510 | 548426 | 2014-09-29 | 2014-09-29 | 1976-01-01 |
+----------+--------------+----------------+------ --------+------------+
| 499510 | 548428 | 2014-01-29 | 2014-01-29 | 1976-01-01 |
+----------+--------------+----------------+------ --------+------------+
| 499510 | 548425 | 2012-05-28 | 2012-05-28 | 1976-01-01 |
+----------+--------------+----------------+------ --------+------------+
| 499510 | 548429 | 2011-11-23 | 2011-11-23 | 1976-01-01 |
+----------+--------------+----------------+------ --------+------------+
| 499510 | 548427 | 2008-07-03 | 2008-07-03 | 1976-01-01 |
+----------+--------------+----------------+------ --------+------------+
| 499510 | 548431 | 2001-05-01 | 1976-01-01 | 1976-01-01 |
+----------+--------------+----------------+------ --------+------------+
| 499510 | 548430 | 1998-10-08 | 1998-10-08 | 1998-10-08 |
+----------+--------------+----------------+------ --------+------------+

请注意:我在传输表中添加了一个 pid 列。第一次忘记包括在内。

谢谢!

4

1 回答 1

1

我认为这是准确的结果……尽管它与您的预期不同。请参阅我上面的评论。

由于第一个表是 CTE,您可以将其保留为 CTE 并继续使用此 CTE,或者将这些结果存储到临时表中,这可能是有益的,因为我们将多次查询它。

declare @Memberships table (PersonID int, MemberShipID int, MembershipDate varchar(16), CServiceDate varchar(16))
insert into @Memberships
values
(1,15,'Aug-01-2016','Aug-27-2017'),
(1,16,'Mar-25-2016','Sep-01-2000'),
(1,17,'Dec-06-2011','May-15-1995'),
(1,18,'Jan-12-2009','Feb-28-1998'),
(1,19,'Apr-08-2016','Jul-10-1994'),
(1,20,'Jun-11-2010','Nov-12-1997') 

declare @Transfer table (TID int, FromMembershipID int, ToMembershipID int)
insert into @Transfer
values
(1,16,15),
(2,18,17),
(3,19,17),
(4,20,18),
(5,20,19)

;with cte as(
select
    m.PersonID
    ,m.MemberShipID
    ,m.MembershipDate
    ,m.CServiceDate
    ,case when t.FromMembershipID <> m.MemberShipID then t.FromMembershipID else t.ToMembershipID end RelatedMemberShips
from
    @Memberships m
    left join
    @Transfer t on
    t.FromMembershipID = m.MemberShipID or t.ToMembershipID = m.MemberShipID)

select distinct
    cte.PersonID
    ,cte.MemberShipID
    ,cte.MembershipDate
    ,cte.CServiceDate
    --,cte.RelatedMemberShips
    --,m.MembershipDate
    --,m.CServiceDate
    ,case when min(convert(date, replace(m.CServiceDate, '-', ' '), 0)) over (partition by cte.MemberShipID) < convert(date, replace(cte.CServiceDate, '-', ' '), 0) then min(convert(date, replace(m.CServiceDate, '-', ' '), 0)) over (partition by cte.MemberShipID)  else convert(date, replace(cte.CServiceDate, '-', ' '), 0) end
from 
    cte
    left join 
        @Memberships m on m.MemberShipID = cte.RelatedMemberShips
        and convert(date, replace(m.MembershipDate, '-', ' '), 0) <= convert(date, replace(cte.MembershipDate, '-', ' '), 0)

或者,您可以在 LINE 中编写此代码并一起跳过 CTE...

select distinct
    m.PersonID
    ,m.MemberShipID
    ,m.MembershipDate
    ,m.CServiceDate
    --,case when t.FromMembershipID <> m.MemberShipID then t.FromMembershipID else t.ToMembershipID end RelatedMemberShips
    ,case when min(convert(date, replace(m2.CServiceDate, '-', ' '), 0)) over (partition by m.MemberShipID) < convert(date, replace(m.CServiceDate, '-', ' '), 0) then min(convert(date, replace(m2.CServiceDate, '-', ' '), 0)) over (partition by m.MemberShipID)  else convert(date, replace(m.CServiceDate, '-', ' '), 0) end
from
    @Memberships m
    left join
    @Transfer t on
    t.FromMembershipID = m.MemberShipID or t.ToMembershipID = m.MemberShipID
    left join 
        @Memberships m2 on m2.MemberShipID = case when t.FromMembershipID <> m.MemberShipID then t.FromMembershipID else t.ToMembershipID end
        and convert(date, replace(m2.MembershipDate, '-', ' '), 0) <= convert(date, replace(m.MembershipDate, '-', ' '), 0)
于 2017-08-07T21:33:29.967 回答