C# 使用linq group by语句作为子查询

C# 使用linq group by语句作为子查询,c#,linq,C#,Linq,我有一个很好的查询: var bands = new List<TimeBand>() { new TimeBand(){Region = 10,PeriodId = 5,StartDate = new DateTime(2013, 04, 01),EndDate = new DateTime(2014, 05, 31),DayName = "Friday",StartTime = "00:00",EndTime = "07:0

我有一个很好的查询:

var bands = new List<TimeBand>()
            {
                new TimeBand(){Region = 10,PeriodId = 5,StartDate = new DateTime(2013, 04, 01),EndDate = new DateTime(2014, 05, 31),DayName = "Friday",StartTime = "00:00",EndTime = "07:00"},
                new TimeBand(){Region = 10,PeriodId = 5,StartDate = new DateTime(2013, 04, 01),EndDate = new DateTime(2013, 05, 31),DayName = "Friday",StartTime = "07:00",EndTime = "00:00"},
                new TimeBand(){Region = 10,PeriodId = 4,StartDate = new DateTime(2013, 06, 01),EndDate = new DateTime(2013, 08, 31),DayName = "Saturday",StartTime = "20:00",EndTime = "00:00"}
            };

    var query = (from x in bands
                group x by new {x.Region, x.DayName}
                into grp
                    select new TimeBand()
                    {
                        Region = grp.Key.Region,
                        DayName = grp.Key.DayName,
                        StartDate = grp.Min(x => x.StartDate),
                        EndDate = grp.Max(x => x.EndDate)
                    }).ToList();
var bands=新列表()
{
新时区(){Region=10,PeriodId=5,StartDate=newdatetime(2013,04,01),EndDate=newdatetime(2014,05,31),DayName=“Friday”,StartTime=“00:00”,EndTime=“07:00”},
新时区(){Region=10,PeriodId=5,StartDate=newdatetime(2013,04,01),EndDate=newdatetime(2013,05,31),DayName=“Friday”,StartTime=“07:00”,EndTime=“00:00”},
新时区(){Region=10,PeriodId=4,StartDate=newdatetime(2013,06,01),EndDate=newdatetime(2013,08,31),DayName=“星期六”,StartTime=“20:00”,EndTime=“00:00”}
};
var query=(从带中的x开始)
按新{x.Region,x.DayName}分组x
玻璃钢
选择新时区()
{
Region=grp.Key.Region,
DayName=grp.Key.DayName,
StartDate=grp.Min(x=>x.StartDate),
EndDate=grp.Max(x=>x.EndDate)
}).ToList();
但是,当我按区域和日期名称对结果进行分组时,我没有得到结果中的其他列,即StartTime和EndTime

如果这是一个SQL查询,我会在子查询中使用这个分组结果,并获取其他列

有没有办法修改它,这样我就可以得到GROUPBY语句中没有包含的属性


谢谢

对源项目进行分组后,您就有了分组顺序。如何规划这些小组取决于您。通常在每个组上选择分组键和一些聚合值(SQL就是这样工作的)。但您可以选择每个组本身,或从每个组中选择第一个项目,或从最后一个组项目中选择一些值:

from b in bands
group b by new { b.Region, b.DayName } into g
select new {
   g.Key.Region,
   g.Key.DayName,
   StartDate = g.Min(x => x.StartDate),
   EndDate = g.Max(x => x.EndDate),
   AllBandsFromGroup = g,
   FirstBand = g.First(),
   LastBandPeriod = g.Last().Period
}

如果需要组中所有项目的键和所有值,只需选择整个组:

select grp;
另一个选项是从组中选择所需列的所有值的序列:

select new TimeBand()
{
    Region = grp.Key.Region,
    DayName = grp.Key.DayName,
    StartDates = grp.Select(x => x.StartDate),
    EndDates = grp.Select(x => x.EndDate)
}

只有在不想下拉其他一些列的数据时,才需要这样做。如果您想要所有列,只需使用第一个选项。

似乎您正在尝试查找每个组的最小开始日期和时间以及最大结束日期和时间。如果将日期和时间合并到一个属性中,这可能会容易得多

var query = (from x in bands
                     group x by new { x.Region, x.DayName }
                         into grp
                         select new 
                         {
                             Region = grp.Key.Region,
                             DayName = grp.Key.DayName,
                             MinStartDate = grp.Min(x => x.StartDate),
                             AllStartDates = grp.Select(k => k.StartDate).ToList(),
                             EndDate = grp.Max(x => x.EndDate),
                             AllEndDates = grp.Select(k => k.EndDate).ToList(),
                         }).ToList();
否则,开始日期和时间将需要一个
IComparer
,结束日期和时间将需要另一个

如果不想将日期和时间组合在一起,可以编写方法来获取组合值:

public DateTime GetStart()
{
    int hour = int.Parse(StartTime.Substring(0, 2));
    int minute = int.Parse(StartTime.Substring(3, 2));

    return new DateTime(StartDate.Year, StartDate.Month, StartDate.Day, hour, minute, 0);
}

public DateTime GetEnd()
{
    int hour = int.Parse(EndTime.Substring(0, 2));
    int minute = int.Parse(EndTime.Substring(3, 2));

    return new DateTime(EndDate.Year, EndDate.Month, EndDate.Day, hour, minute, 0);
}
现在,您可以对标注栏进行分组,并为每组找到最小起点和最大终点:

var query = from x in bands
            group x by new
                       {
                           x.Region,
                           x.DayName
                       }
            into grp
            select new TimeBand()
                   {
                       Region = grp.Key.Region,
                       DayName = grp.Key.DayName,
                       StartDate = grp.Min(x => x.StartDate),
                       StartTime = grp.Min(x => x.GetStart()).ToShortTimeString(),
                       EndDate = grp.Max(x => x.EndDate),
                       EndTime = grp.Max(x => x.GetEnd()).ToShortTimeString(),
                   };

然而,这不是很优雅。首先,我希望将日期和时间结合起来。

grp
实现了
IEnumerable
,它包含所有列。您现在只是没有选择它们。@03Usr这是因为没有一个值。序列中的每个项目表示一个项目序列。您可以迭代以获得每个子项。然后,您可以从这些项中的任何一项中提取列值。感谢Servy/Tim S,我已经调试并看到了它。您想要的输出是什么?我运行了您的示例,得到了我所期望的:(10 Friday 01.04.2013 31.05.2014),(10 Saturday 01.06.2013 31.08.2013)到您最后的评论,不,没有
x
groupby
@Servy之后离开了作用域,请稍候check@Servy是的,您是对的-不知道分组“关闭”查询变量的可见性。感谢我加入一个团队会发生一些事情