2013-11-01 25 views
2

我有以下查詢工作正常:通過聲明使用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: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(); 

但正如我組按地區和DAYNAME我不會在我的結果讓另一列即開始時間和結果時間結束。

如果這是一個SQL查詢,我會在子查詢中使用這個分組結果,並獲取其他列。

有什麼辦法可以修改這個,所以我也得到了不屬於group by語句的屬性。

謝謝

+0

'grp'實現了'IEnumerable <>',它具有所有的列。你現在根本沒有選擇它們。 –

+0

@ 03Usr這是因爲不只有一個價值。序列中的每個項目表示一系列項目。你可以迭代*那*得到每個子項。然後,您可以從任何這些項目中提取列值。 – Servy

+0

謝謝Servy/Tim S我已經調試過並看過它。 – 03Usr

回答

1

在對源項目進行分組後,您將獲得組的序列。你將如何投影這些組是由你決定的。通常你在每個組中選擇分組鍵和一些聚合值(這就是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 
} 
+1

對你最後的評論,不,它不。在'group by'之後''x留下了範圍。 – Servy

+0

@Servy堅持,我會檢查 –

+0

@Servy你是對的 - 不知道該分組關閉查詢變量的可見性。謝謝 –

1

如果你想要的按鍵以及所有的所有的值就選擇了全組在團體項目:

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) 
} 

你只需要做的這個我如果您不想將某些其他列的數據拉下來。如果你想要所有的列,只需使用第一個選項。

1
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(); 
0

看來你正在努力尋找最小的開始日期時間和最大結束日期時間爲每個組。如果將日期和時間組合到一個屬性中,這可能會更容易。

否則,您需要一個IComparer<TimeBand>作爲開始日期和時間,另一個作爲結束日期和時間。

如果你不想日期和時間,你可以寫的方法來獲取合併值組合:

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(), 
        }; 

但是,這是不是很優雅。我寧願把日期和時間放在首位。