通过删除重叠的行

时间:2017-06-14 14:38:17

标签: c# linq

我的客户会员记录集如下所示。

        CustomerId | EffectiveDate | EndDate | RecordNo
        A1 | 01 - 01 - 2016 | 31 - 05 - 2016 | 1
        A1 | 01 - 06 - 2016 | 31 - 10 - 2016 | 2
        A1 | 01 - 09 - 2016 | 31 - 12 - 2017 | 3
        A1 | 02 - 11 - 2016 | 31 - 12 - 2016 | 4
        A2 | 02 - 11 - 2016 | 31 - 12 - 2016 | 5

要求是

  • 连续日期需要合并为1个日期范围
  • 如果给定客户ID的日期重叠,则应删除该行

因此我的结果集应如下所示

            CustomerId | EffectiveDate | EndDate | IsBad
            A1 | 01 - 01 - 2016 | 31 - 10 - 2016 | false
            A1 | 01 - 09 - 2016 | 31 - 12 - 2017 | true
            A1 | 02 - 11 - 2016 | 31 - 12 - 2016 | false
            A2 | 02 - 11 - 2016 | 31 - 12 - 2016 | false

对于Customer A1,1个重叠行被设置为拒绝(IsBad属性设置为true)。 彼此相邻的2行组合成1个日期范围。 但是记录号4保持原样,因为它们是一天的间隙(它不是连续的)

数据存储在List<CustomerMembership>() CustomerMembership类中CustomerIdEffectiveDateEndDateIsBad属性。

编辑 - 问题是如何在给定输入(第一组数据)的情况下获得所需的输出(第二组数据)?

先谢谢

1 个答案:

答案 0 :(得分:0)

假设记录4没有重叠记录3,因为记录3被标记为坏,并且假设最多两个记录可以组合成一个记录,这些查询将合并两个记录然后for循环是查找错误记录的最有效方法。它可以通过LINQ完成,但它会涉及多次传递数据以获得很少的收益。

// find records that extend an earlier record
var step0 = from r1 in src
            join r2 in src.Skip(1) on new { r1.CustomerId, TestDate = r1.EndDateTime.AddDays(1) } equals new { r2.CustomerId, TestDate = r2.EffectiveDateTime }
            select new { r1, r2 };

// combine extended records and passthru non-extended records
var step1 = (from r1 in src
            where !step0.Any(r1r2 => r1 == r1r2.r1)
            join r1r2 in step0 on r1 equals r1r2.r1 into r1r2j
            from r1r2 in r1r2j.DefaultIfEmpty()
            let r2 = r1r2?.r2
            orderby r1.CustomerId, r1.EffectiveDateTime
            select new CustomerMembership { CustomerId = r1.CustomerId, EffectiveDateTime = r1.EffectiveDateTime, EndDateTime = (r2 != null) ? r2.EndDateTime : r1.EndDateTime }).ToArray();

// find bad records by comparing records to previous record
for (var j1 = 1; j1 < step1.Length; ++j1)
    if (!step1[j1-1].IsBad)
        step1[j1].IsBad = step1[j1].CustomerId == step1[j1-1].CustomerId &&
            (step1[j1].EffectiveDateTime.IsBetween(step1[j1-1].EffectiveDateTime, step1[j1-1].EndDateTime) ||
            step1[j1].EndDateTime.IsBetween(step1[j1-1].EffectiveDateTime, step1[j1-1].EndDateTime));

var ans = step1.ToList();