2017-07-28 3 views
-1

私はいくつかのカウントを行い、グループ化する必要がある問題に取り組んでいます。私は仕事でそれをしようとしましたが、1つのクエリでそれを行うことができませんでした。もちろん、私はそれを分割して答えを得ることができますが、誰かが私が1つの声明で答えを見つけるのを手助けできるかどうか不思議です。解読せずに答えを返す1つのLINQステートメント

以下は、必要なコードと回答です。

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Web; 
using System.Web.UI; 
using System.Web.UI.WebControls; 

namespace GetCountInfo 
{ 
    public partial class _Default : Page 
    { 
     protected void Page_Load(object sender, EventArgs e) 
     { 
      /* 
      * 
      * 
      * current Date would be: 7/27/2017 4:00 PM 
      * 
      ReportOutOfDateCountDto 

      The answer would be: 

      Patrick = Count of 1 
      Stacy = Count of 2 

      */ 
     } 

     /// <summary> 
     /// This is the data for each year nbr 
     /// </summary> 
     /// <returns></returns> 
     public IList<YearNbrInfoDto> GetYearInfoData() 
     { 
      IList<YearNbrInfoDto> theData = new List<YearNbrInfoDto>(); 

      theData.Add(new YearNbrInfoDto { RecordId = 1, YearNbr = 0, CreateDt = new DateTime(2014,1,6) }); // out of date 
      theData.Add(new YearNbrInfoDto { RecordId = 1, YearNbr = 1, CreateDt = new DateTime(2014, 5, 6) }); // out of date 
      theData.Add(new YearNbrInfoDto { RecordId = 1, YearNbr = 2, CreateDt = new DateTime(2015, 1, 22) }); // out of date 
      theData.Add(new YearNbrInfoDto { RecordId = 1, YearNbr = 3, CreateDt = new DateTime(2018, 5, 6) }); // NOT out of date 

      // Above would just be a count of 1 because there are 3 that are out of date, but they all have the same record id, so it would just be 1 record id 

      theData.Add(new YearNbrInfoDto { RecordId = 2, YearNbr = 0, CreateDt = new DateTime(2019, 5, 6) }); // NOT out of date 
      theData.Add(new YearNbrInfoDto { RecordId = 2, YearNbr = 1, CreateDt = new DateTime(2018, 1, 6) }); // NOT out of date 

      // Above would not be calculated because none of the Record Ids are out of date 

      theData.Add(new YearNbrInfoDto { RecordId = 5, YearNbr = 0, CreateDt = new DateTime(2014, 3, 3) }); // out of date 
      theData.Add(new YearNbrInfoDto { RecordId = 5, YearNbr = 1, CreateDt = new DateTime(2015, 3, 6) }); // out of date 
      theData.Add(new YearNbrInfoDto { RecordId = 5, YearNbr = 2, CreateDt = new DateTime(2017, 10, 3) }); // NOT out of date 
      theData.Add(new YearNbrInfoDto { RecordId = 5, YearNbr = 3, CreateDt = new DateTime(2018, 1, 6) }); // NOT out of date 

      // Above would just be a count of 1 because there are 2 that are out of date, but they all have the same record id, so it would just be 1 record id 

      theData.Add(new YearNbrInfoDto { RecordId = 6, YearNbr = 0, CreateDt = new DateTime(2014, 3, 3) }); // out of date 
      theData.Add(new YearNbrInfoDto { RecordId = 6, YearNbr = 1, CreateDt = new DateTime(2018, 3, 6) }); // NOT out of date 
      theData.Add(new YearNbrInfoDto { RecordId = 6, YearNbr = 2, CreateDt = new DateTime(2019, 1, 3) }); // NOT out of date 
      theData.Add(new YearNbrInfoDto { RecordId = 6, YearNbr = 3, CreateDt = new DateTime(2020, 1, 6) }); // NOT out of date 

      // Above would just be a count of 1 because there is 1 that is out of date 

      return theData; 
     } 

     /// <summary> 
     /// This ties the Year Record info to the user ids 
     /// </summary> 
     /// <returns></returns> 
     public IList<MainRecordInfoDto> GetMainRecordInfoData() 
     { 
      IList<MainRecordInfoDto> theData = new List<MainRecordInfoDto>(); 

      theData.Add(new MainRecordInfoDto { UserId = 1, RecordId = 1 }); 
      theData.Add(new MainRecordInfoDto { UserId = 1, RecordId = 2 }); 
      theData.Add(new MainRecordInfoDto { UserId = 1, RecordId = 3 }); 
      theData.Add(new MainRecordInfoDto { UserId = 1, RecordId = 4 }); 


      theData.Add(new MainRecordInfoDto { UserId = 2, RecordId = 5 }); 
      theData.Add(new MainRecordInfoDto { UserId = 2, RecordId = 6 }); 

      return theData; 
     } 

     /// <summary> 
     /// This is the main User info... 
     /// </summary> 
     /// <returns></returns> 
     public IList<UserInfoDto> GetUserInfoData() 
     { 
      IList<UserInfoDto> theData = new List<UserInfoDto>(); 

      theData.Add(new UserInfoDto { Name = "Patrick", UserId = 1 }); 
      theData.Add(new UserInfoDto { Name = "Stacy", UserId = 2 }); 

      return theData; 
     } 
    } 

    public class ReportOutOfDateCountDto 
    { 
     public string Name { get; set; } 

     /// <summary> 
     /// This would be the count of out of date PER RecordId 
     /// </summary> 
     public int CountOfOutOfDateYearNbrs { get; set; } 

    } 

    public class YearNbrInfoDto 
    { 

     public int RecordId { get; set; } 

     public int YearNbr { get; set; } 

     public DateTime CreateDt { get; set; } 
    } 

    public class MainRecordInfoDto 
    { 
     public int UserId { get; set; } 

     public int RecordId { get; set; } 
    } 

    public class UserInfoDto 
    { 
     public string Name { get; set; } 
     public int UserId { get; set; } 
    } 
} 
+1

2つのクエリで試したコードを表示できますか? – Fabio

+0

Unfortunatelそれは働いています:-( – user272727

答えて

1

をあなたが短く、はるかに効率的なクエリのリレーショナルデータを結合することができます。

var result = GetYearInfoData() 
    .Where(d => d.CreateDt < DateTime.Now) 
    .Select(x => x.RecordId)         // RecordIds 1, 1, 1, 5, 5, 6 
    .Distinct()               // RecordIds 1, 5, 6 
    .Join(GetMainRecordInfoData(), i => i, r => r.RecordId, (i, r) => r.UserId) // UserIds 1, 2, 2 
    .Join(GetUserInfoData()  , i => i, u => u.UserId , (i, u) => u.Name ) // Names { Patrick, Stacy, Stacy } 
    .GroupBy(n => n) 
    .Select(g => new { Name = g.Key, Count = g.Count() }); // Names and Counts 

データがデータベースからではない場合、それが作成することによって、さらに最適化することができ、クエリの前にルックアップ:

var yearLookup = GetYearInfoData().ToLookup(y => y.RecordId); 
var recordLookup = GetMainRecordInfoData().ToLookup(r => r.UserId); 

var result = GetUserInfoData().Select(u => new { u.Name, Count = recordLookup[u.UserId] 
    .Count(i => yearLookup[i.RecordId].Any(d => d.CreateDt < DateTime.Now)) }); 
+0

ありがとうございます - 私はあなたの答えが良い! – user272727

0

私は答えを得たと思っていますが、本当に理解できません。下記をご覧ください:

var tblYearInfoData = GetYearInfoData(); 

var tblMainRecordInfoData = GetMainRecordInfoData(); 

var tblGetUserInfoData = GetUserInfoData(); 

var thisWillNeverWork = (from yfd in tblYearInfoData 
         where yfd.CreateDt < DateTime.Now // Pull all the record ids where the create dt is out of date... i.e. in the past... 
         select new 
         { 
          RecordId = yfd.RecordId // Select those record ids.... 
         }) 
         .GroupBy(gb => gb.RecordId) // Now group by the record ids... so if there is one record id.... and there are 3 that are out of date... it will combine it to 1... 
         .Select(selectGroup1 => new 
         { 
          RecordId = selectGroup1.Key, // This will get the grouped by record ids... 

          // Get the User Id so then we can do a final count with the name 
          UserId = tblMainRecordInfoData.Where(w => w.RecordId == selectGroup1.Key).Select(s => s.UserId).FirstOrDefault() 
         }).GroupBy(gb => gb.UserId) // Then we group by user id.... 
          .Select(selectGroup2 => new ReportOutOfDateCountDto 
          { 
          Name = tblGetUserInfoData.Where(w => w.UserId == selectGroup2.Key).Select(s => s.Name).FirstOrDefault(), // we use the user id grouped by... to get the name 
          CountOfOutOfDateYearNbrs = selectGroup2.Count() // then we do a count on the group by and somehow it worked... haha not sure how :-) 
          }).ToList(); 
関連する問題