我正在研究一个需要做一些计数和分组的问题。我曾尝试在工作中这样做,但无法在一个查询中执行此操作。当然,我可以将其拆分并得到答案,但我很好奇是否有人可以帮助我在一个声明中找到答案?
以下是我需要的代码和答案。
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; }
}
}
答案 0 :(得分: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)) });
答案 1 :(得分: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();