2017-06-14 11 views
-1

私は以下のようにCustomer Membership Recordセットを持っています。重複する行を削除して連続した日付範囲を短縮します

 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 

要件は

  • 連続日数は、行が削除されるべき所与の顧客IDの日付の重複がある場合は1つの日付範囲
  • に結合する必要がある

私の結果セットは次のようになります

  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 

これは、顧客A1、1の重複行が拒否に設定されている(IsBadプロパティがtrueに設定されている)場合です。 2つの隣接する行が1つの日付範囲に結合されました。 しかし、彼らは一日のギャップがあったため、そのままレコード番号4が保持された

データCustomerMembershipクラスがCustomerIdEffectiveDateEndDateIsBad特性を有するList<CustomerMembership>()に格納されている(それは連続しませんでした)。

編集 - 入力(1番目のデータセット)が与えられた場合、どのようにして目的の出力(2番目のデータセット)を得ることができますか?事前に

おかげ

+0

[質問タイトルにタグを入れないでください](https://stackoverflow.com/help/tagging) – Liam

+0

どうしますか? – Liam

+0

次試してみてください:varが(dt.AsEnumerableにeffdateから=参加) は(dt.AsEnumerableで終了日に参加)effdate.Field ( "終了日")にAddDaysは、(1)enddate.Field ( "EffectiveDate") に等しいです。新しい{effdate = effdate、enddate = enddate}を選択します。 – jdweng

答えて

0

記録3が不良とマークされているので、レコード4レコード3と重ならないと仮定すると、ほとんどの2つのレコードが1つのレコードに組み合わせることが可能で、これらのクエリは、2つのレコードを結合してからになると仮定すると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(); 
関連する問題