Объединение двух разных совокупных запросов: возможно? (EF Core 5, SQL Server)

У меня есть такая таблица:

идентификатор (ПК)названиекурсдатаоценка
1ДжейнФранцузский20.11.201620
3КАРЛФранцузский2015-09-0230
4АннаФранцузский20.11.201625
5ДЖОНФранцузский2016-09-0256
6Линдаанглийский2016-09-0222
7ТИМанглийский20.11.201623
8ДЖОНанглийский20.11.201644

и мне интересно, можно ли ответить на следующие два вопроса одним запросом:

  • Какова средняя оценка при группировке по курсам среди всех зачисленных студентов во все даты курса? (это кажется более простым, так как грубо сгруппируйте по нескольким столбцам, а затем возьмите среднее значение столбца «оценка»).

  • Каково среднее количество студентов, записавшихся на каждый курс по дате? Другими словами, «на английском языке», поскольку два студента были зачислены 11-20, а один студент был зачислен 09-02, среднее количество зачисленных студентов на дату занятия составляет 1,5.

Можно ли ответить на оба этих вопроса одним запросом? Или это так, что, поскольку я буду «группировать» по разным столбцам, я не могу добиться этого в одном запросе?

Я использую EF Core 5.0, поддерживаемый базой данных SQL Server, поэтому было бы неплохо, если бы я мог добиться этого с помощью оператора LINQ groupby, но если нет, я не возражаю против написания прямого SQL, если это более эффективно.

Формы c голосовым вводом в React с помощью Speechly
Формы c голосовым вводом в React с помощью Speechly
Пытались ли вы когда-нибудь заполнить веб-форму в области электронной коммерции, которая требует много кликов и выбора? Вас попросят заполнить дату,...
Стилизация и валидация html-формы без использования JavaScript (только HTML/CSS)
Стилизация и валидация html-формы без использования JavaScript (только HTML/CSS)
Будучи разработчиком веб-приложений, легко впасть в заблуждение, считая, что приложение без JavaScript не имеет права на жизнь. Нам становится удобно...
Flatpickr: простой модуль календаря для вашего приложения на React
Flatpickr: простой модуль календаря для вашего приложения на React
Если вы ищете пакет для быстрой интеграции календаря с выбором даты в ваше приложения, то библиотека Flatpickr отлично справится с этой задачей....
В чем разница между Promise и Observable?
В чем разница между Promise и Observable?
Разберитесь в этом вопросе, и вы значительно повысите уровень своей компетенции.
Что такое cURL в PHP? Встроенные функции и пример GET запроса
Что такое cURL в PHP? Встроенные функции и пример GET запроса
Клиент для URL-адресов, cURL, позволяет взаимодействовать с множеством различных серверов по множеству различных протоколов с синтаксисом URL.
Четыре эффективных способа центрирования блочных элементов в CSS
Четыре эффективных способа центрирования блочных элементов в CSS
У каждого из нас бывали случаи, когда нам нужно отцентрировать блочный элемент, но мы не знаем, как это сделать. Даже если мы реализуем какой-то...
0
0
43
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Объединить их будет несколько сложнее, и это практически невозможно сделать в EF/Linq. Я бы сказал, что это того стоит, только если дважды запрашивать таблицу крайне неэффективно. В противном случае просто выполните их либо в EF, либо в виде одного пакета T-SQL из двух запросов.

  • На первый запрос можно было легко ответить в T-SQL.
SELECT
  c.Course,
  AVG(c.Grade * 1.0) AvgGrade
FROM Course c
GROUP BY
  c.Course;

И в Линке

from c in Course
group by c.Course into g
select new {
    Course: g.Key,
    AvgGrade: g.Avg(c2 => c2.Grade * 1.0)
}

  • Аналогично, другой запрос
SELECT
  c.Course,
  AVG(Count * 1.0) AvgCount
FROM (
    SELECT
      c.Course,
      COUNT(*) Count
    FROM Course c
    GROUP BY
      c.Course,
      c.Date
) c
GROUP BY
  c.Course;

И в Линке

from c in Course
group by new {c.Course, c.Date} into g
select new {
    Course: g.Key.Course,
    Count: g.Count()
} into c2
group by c2.Course into g2
select new {
    Course: g2.Key,
    AvgCount: g2.Average(c3 => c3.Count * 1.0)
}

Чтобы совместить это, вы можете использовать следующее:

Это усложняется тем фактом, что уже есть агрегирование, и вы не можете (математически) вычислить средние значения по средним. Поэтому вам нужно использовать SUM / COUNT и вложить группировку.

SELECT
  c.Course,
  AVG(Count * 1.0) AvgCount,
  SUM(c.TotalGrades) * 1.0 / SUM(Count) AvgGrade
FROM (
    SELECT
      c.Course,
      COUNT(*) Count,
      SUM(c.Grade) TotalGrades
    FROM Course c
    GROUP BY
      c.Course,
      c.Date
) c
GROUP BY
  c.Course;

И в Линке

from c in Course
group by new {c.Course, c.Date} into g
select new {
    Course: g.Key.Course,
    Count: g.Count(),
    TotalGrades: g.Sum(c3 => c3.Grade)
} into c2
group by c2.Course into g2
select new {
    Course: g2.Key,
    AvgCount: g2.Average(c3 => c3.Count * 1.0).
    AvgGrade: g2.Sum(c3 => c3.TotalGrades) * 1.0 / g2.Sum(c3 => c3.Count)
}

дб <> рабочий пример

Спасибо, Чарлифейс, это очень полезно. Я почитаю о групповых наборах, хотя я думаю, что лучший путь вперед - это два отдельных запроса для простоты. Для второго запроса это близко, но я не думаю, что именно мне нужно: это дает мне группу для каждой комбинации курса/даты, но мне нужна просто группа для каждого курса, заполненная значением среднего количества по датам. Я мог бы легко добиться этого, выполнив некоторую постобработку для каждого набора групп, но есть ли способ сделать это в одном запросе? Итак, на английском языке у нас было два абитуриента в один день и 1 в другой, поэтому результат = 1,5.

BenjiFB 17.05.2022 15:10

Извините, если эта часть моего вопроса была неясна.

BenjiFB 17.05.2022 15:10

О, тогда все намного проще. См. правки

Charlieface 17.05.2022 15:59

Другие вопросы по теме