LINQ групповой оператор с ключом - PullRequest
7 голосов
/ 10 марта 2011

Синтаксис моего запроса хорош, но не выводится, и это действительно странно.

У меня есть следующая таблица:

| 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 - это дата в месяце, к которому я обращаюсь (т. Е. Пройти 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 запросами и присоединяюсь к результатам: один запрос возвращает набор назначенных встреч, а другой возвращает разрешенные встречи.Тем не менее, я по-прежнему застрял в решении с одним запросом в одном чтении.

Есть предложения?

Спасибо.

Ответы [ 3 ]

2 голосов
/ 11 марта 2011

Вам необходимо сгруппировать, используя как Установленную дату, так и Решенную дату. Этого легко достичь, добавив еще одно предложение from, выполняющее перекрестное соединение с набором дат и группирующее по этим датам.

Запрос ниже основан на запросе LINQ to Objects. 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),
            };
1 голос
/ 11 марта 2011

Вы группируете по AppointResolved.Date.

Таким образом, для каждой записи в дневных группах 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 голосов
/ 15 марта 2011

Полагаю, решение с двумя запросами на чтение прекрасно работает и пока будет работать.

...