2011-03-10 88 views
7

我的查詢語法很好,但不是輸出,它真的很奇怪。LINQ groupby statement with key

我有以下表:

| AppointID | UserID | AppointSet | AppointResolved | AppointStatus | AppointmentDatetime 
|  1  | 1 | 3/1/2011 | 3/1/2011  |  1   |  3/15/2011 
|  2  | 1 | 3/2/2011 | 3/5/2011  |  4   |  3/16/2011 
|  3  | 1 | 3/2/2011 | 3/11/2011  |  2   |  3/11/2011 
|  4  | 1 | 3/3/2011 | 3/7/2011  |  3   |  3/25/2011 

ApponintStatus是一個字節,其中1是用於組,圖2是用於參加,圖3是用於經重組和圖4是用於取消。 AppointDatetime是約會設置的日期。

我想要做的就是創建下面的輸出,通過計算一天的活動。

| Date  | Set | Attended | Rescheduled | Cancelled | 
| 3/1/2011 | 1 |    |     |    | 
| 3/2/2011 | 2 |    |     |    | 
| 3/3/2011 | 1 |    |     |    | 
| 3/5/2011 |   |    |     |  1  | 
| 3/7/2011 |   |  1  |     |    | 
| 3/11/2011 |   |    |  1  |    | 

這是我到目前爲止。 TheDate是我查詢一個月內的日期(即,通過3月4日,應退還三月表)

var r = from appnt in MyDC.LeadsAppointments 
     where appnt.UserID == TheUserID 
     where (appnt.AppointResolved.Year == TheDate.Year && appnt.AppointResolved.Month == TheDate.Month) || 
     (appnt.AppointSet.Year == TheDate.Year && appnt.AppointSet.Month == TheDate.Month) 
     group appnt by appnt.AppointResolved.Date into daygroups 
     select new ViewMonthlyActivityModel() 
     { 
      ViewDate = (from d in daygroups 
         select daygroups.Key.Date).First(), // Problem here: need to get dates for instances where an appointment is set but none are resolved 

      CountTotalSetOnDay = (from c in daygroups 
            where c.AppointSet.Date == daygroups.Key // Problem here 
            select c.AppointID).Count(), 

      CountAttendedOnDay = (from c in daygroups 
            where c.AppointResolved.Date == daygroups.Key.Date 
            where c.AppointStatus == 2 
            select c.AppointID).Count(), 

一個問題是,CountTotalSetOnDay將返回只有那些設置和計數同一天解決;另一個問題是ViewDate需要返回所有的日期:有沒有設置約會但約會出席,重新安排或取消的日期,反之亦然,有約會設置但沒有解決的日期。

現在我有2個查詢運行此,我加入了結果:一個查詢返回設置的約會和其他收益的任命得到解決。然而,我仍然堅持在一次閱讀中一個查詢的解決方案。

有什麼建議嗎?

謝謝。

回答

0

我猜這個解決方案有兩個讀取查詢的工作很好,現在就代表着。

1

你被AppointResolved.Date分組。

因此,對於daygroups中的每個條目,daygroups.Key == AppointResolved.Date和c.AppointSet.Date == daygroups.Key where子句將只給你約會設置在同一天的所有條目因爲它已經解決了。

在我看來,如果你想實現自己的既定目標,你必須列出你的任何表的字段中提到的所有日期和計數。

例如,請考慮:

var appointmentsTaken = (from appnt in GoyaDC.LeadsAppointments 
         where ... // your filters 
         group appnt by appnt.AppointSet.Date into daysset 
         select { Date = daysset.Key Count = daysset.Count() } 

這應該給你的日期列表,其中任命其中一組,併爲每個,其中有多少人。

+0

是的,這就是我堅持的問題。而且,還有一些情況是有約會的日期,但沒有約定的約會。 – frenchie 2011-03-10 21:49:55

+0

這令人困惑;這個var約會取走了哪裏? – frenchie 2011-03-10 21:55:11

+0

這只是一個示例,向您展示如何從表條目中獲取「設置」列。如果您對輸出表中的每個日期和每個必填字段都做同樣的事情,則應該擁有完成目標所需的所有信息。 – tugudum 2011-03-10 21:59:05

2

您需要使用組同時設置日期和解決日期。這很容易通過添加另一個from子句與日期集合進行交叉連接並按這些日期分組來實現。

下面的查詢是基於LINQ到對象的查詢。 LINQ to SQL不支持這種查詢,因此您必須決定是否要使用在客戶機或服務器上運行的查詢。

const byte statusAttended = 2; 
const byte statusRescheduled = 3; 
const byte statusCancelled = 4; 
var query = from a in MyDC.LeadsAppointments.AsEnumerable() 
      from date in new[] { a.AppointSet.Date, a.AppointResolved.Date } 
      where a.UserID == TheUserID 
       && date.Year == TheDate.Year 
       && date.Month == TheDate.Month 
      group a by date into g 
      orderby g.Key 
      let set = g.Distinct().ToList() 
      select new ViewMonthlyActivityModel 
      { 
       ViewDate = g.Key, 
       CountTotalSetOnDay = 
        set.Count(a => a.AppointSet.Date == g.Key), 
       CountTotalAttendedOnDay = 
        set.Count(a => a.AppointResolved.Date == g.Key 
           && a.AppointStatus == statusAttended), 
       CountTotalRescheduledOnDay = 
        set.Count(a => a.AppointResolved.Date == g.Key 
           && a.AppointStatus == statusRescheduled), 
       CountTotalCancelledOnDay = 
        set.Count(a => a.AppointResolved.Date == g.Key 
           && a.AppointStatus == statusCancelled), 
      }; 

否則,對於一個完全的LINQ to SQL解決方案(不乾淨的)應該工作,你可以試試這個。可能有更好的方法來做到這一點,但我不知道。

const byte statusAttended = 2; 
const byte statusRescheduled = 3; 
const byte statusCancelled = 4; 
var query = from a in MyDC.LeadsAppointments 
      let setDate = from aa in MyDC.LeadsAppointments 
          where aa.AppointID == a.AppointID 
          select aa.AppointSet.Date 
      let resolvedDate = from aa in MyDC.LeadsAppointments 
           where aa.AppointID == a.AppointID 
           select aa.AppointResolved.Date 
      from date in setDate.Concat(resolvedDate) 
      where a.UserID == TheUserID 
       && date.Year == TheDate.Year 
       && date.Month == TheDate.Month 
      group a by date into g 
      orderby g.Key 
      let set = g.Distinct() 
      select new ViewMonthlyActivityModel 
      { 
       ViewDate = g.Key, 
       CountTotalSetOnDay = 
        set.Count(a => a.AppointSet.Date == g.Key), 
       CountTotalAttendedOnDay = 
        set.Count(a => a.AppointResolved.Date == g.Key 
           && a.AppointStatus == statusAttended), 
       CountTotalRescheduledOnDay = 
        set.Count(a => a.AppointResolved.Date == g.Key 
           && a.AppointStatus == statusRescheduled), 
       CountTotalCancelledOnDay = 
        set.Count(a => a.AppointResolved.Date == g.Key 
           && a.AppointStatus == statusCancelled), 
      }; 
+0

我測試並重新測試它,但它沒有返回正確的結果對付虛擬數據。我不知道爲什麼。 – frenchie 2011-03-14 21:01:07

+0

@frenchie:這兩者之間有什麼不對?使用您的示例數據,它與輸出相匹配(交換日期和重新計劃的日期)。你有沒有遺漏的案件? – 2011-03-14 22:20:14

+0

我不知道爲什麼它不起作用,但是當我根據樣本數據測試查詢的輸出時,結果是不同的。例如,在CountTotalSetDay上,我所有的樣本數據都被設計爲每天顯示16個計數,並且使用這個查詢我每天得到40個計數。我放在一起的查詢工作正常。它首先獲取所有Set,然後獲取所有其他案例,然後將它們與linq-to-object查詢結合起來。是的,它有兩個讀取,但目前我要離開它。你的代碼顯示了「let」聲明的工作原理,這對我有其他幫助。謝謝。 – frenchie 2011-03-15 01:45:10