2011-03-10 14 views
7

Sorgumun sözdizimi iyi ama çıktı değil ve gerçekten garip.LINQ groupby bildirimi

| 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 3 yeniden planlanan içindir ve 4 iptal için, 2 katıldı, 1 grubu için bir bayt olup:

Aşağıdaki tablo var. AppointDatetime, randevunun ayarlandığı tarihtir.

Yapmaya çalıştığım şey, etkinliği güne göre sayan aşağıdaki çıktıyı oluşturmaktır.

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

Şimdiye dek sahip olduğum şey budur. Ben sorgulama ediyorum ay içinde bir tarih thedate olan CountTotalSetOnDay ayarlanmış olanlara ve sadece sayımını dönüyor bu sorunun

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

biri (yani 4 Mart'tan geçmek ve Mart tablo dönmelidir) aynı gün çözüldü; Diğer problem ViewDate'in tüm tarihleri ​​geri göndermesi gerektiğidir: atanmış randevu yokken randevuların olduğu, randevu alındığı veya iptal edildiği veya tam tersi, randevuların ayarlandığı fakat hiçbirinin çözülmediği tarihler vardır.

Şimdilik bunu 2 sorgu ile çalıştırıyorum ve sonuçlara katılıyorum: bir sorgu, randevuları döndürür ve diğeri, çözülen randevuları döndürür. Ancak, hala bir okuma ile bir sorgu ile çözüm üzerinde sıkışmış.

Herhangi bir öneriniz var mı?

Teşekkürler.

cevap

0

2 okuma sorgusuyla çözüm gayet iyi çalışıyor ve şimdilik duracak.

1

AppointResolved.Date tarafından gruplandırılıyorsunuz.

Bu nedenle, günlük gruplarındaki her bir girdi için, daygroups.Key == AppointResolved.Date ve c.AppointSet.Date == daygroups.Key, burada yalnızca randevunun aynı gün ayarlandığı tüm girdileri verir. çözüldüğü gibi.

Belirttiğiniz hedefe ulaşmak istiyorsanız, tablonuzun herhangi bir alanında belirtilen tüm tarihleri ​​listelemek ve saymak zorunda kalacaksınız. Örneğin

, düşünün:

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

Bu, tarihlerin bir listesini vermelidir nerede randevular nereye seti, ve her biri için, kaç tanesinin.

+0

Evet, bu benim takıldığım sorun. Ayrıca, bir randevu ayarının olduğu ancak randevunun çözülmediği bir tarih olduğu durumlar da olacaktır. – frenchie

+0

Bu kafa karıştırıcı; Bu randevuları nereye alıyor? – frenchie

+0

Sadece 'Giriş' sütununu tablo girişlerinizden nasıl alacağınızı gösteren bir örnek. Her bir tarih ve çıkış tablonuzdaki her alan için aynı şeyi yaparsanız, hedefinize ulaşmak için ihtiyacınız olan tüm bilgilere sahip olmalısınız. – tugudum

2

Hem Tarihi ayarla hem de Çözümlenmiş tarihi kullanarak grup oluşturmanız gerekir. Bu, tarihler kümesine çapraz birleştirme yaparak ve bu tarihlere göre gruplandırılarak başka bir from cümlesi ekleyerek kolayca yapılabilir.

Aşağıdaki sorgu, LINQ to Objects sorgusuna dayanmaktadır. LINQ to SQL bu tür bir sorguyu desteklemez, böylece istemci makinede veya sunucuda çalışan bu yazılımı kullanmak isteyip istemediğinize karar vermeniz gerekir.

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

Aksi çalışmalıdır tamamen LINQ to SQL çözümü (değil en temiz) için, bu deneyebilirsiniz. Bunu yapmanın daha güzel bir yolu olabilir ama ben bunu bilmiyorum.

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

Test ettim ve yeniden test ettim, ancak doğru sonuçları sahte verilerle karşılamıyordu. Nedenini bilmiyorum. – frenchie

+0

@frenchie: Bunlardan herhangi biri hakkında doğru olan nedir? Örnek verilerinizle, çıktıyla eşleşir (katılmış ve yeniden zamanlanmış tarihlerle değiştirilir). Dışarıda bıraktığın durumlar var mı? –

+0

Neden çalışmadığını bilmiyorum, ancak sorgunun çıktısını örnek verilere karşı test ettiğimde sonuçlar farklıdır. Örneğin, CountTotalSetDay'de, tüm örnek verilerim her gün için 16 sayısını gösterecek şekilde tasarlanmıştır ve bu sorguyla her gün için 40'lık bir sayı elde ediyorum. Bir araya getirdiğim sorgu iyi çalışıyor. İlk önce tüm Set'i, sonra tüm diğer durumları alır ve her ikisini de linq-to-object sorgusuyla birleştirir. Evet, 2 okur ama şu an için bunu bırakacağım. Kodunuz "let" ifadesinin nasıl çalıştığını gösterir ve bu bana başka bir şey için yardımcı oldu. Teşekkürler. – frenchie