Как объединить результаты двух запросов в одну таблицу, сгруппированную по YEAR и MONTH? - PullRequest
0 голосов
/ 04 марта 2020

У меня есть две таблицы, materials_students и components_students. У них обоих есть столбец finished_at. material_student имеет столбец component_student_id.

Мне нужно посчитать количество компонентов_студентов и материалов_стадентов (где идентификатор Finish_at не равен NULL), извлечь месяц и год из сигнала Finised_at, сгруппировать результат по месяцу и году и отобразить его в одной таблице, например:

      | Materials  | Components |  Month |  Year
      ---------------------------------------------  
      |   45             3            1     2019
      |   37             6            2     2019
      |   63             8            3     2019 

Я знаю, как сделать это только для одной таблицы, но не знаю, как объединить результаты только в одной таблице.

Ниже показано, как я это сделал для одной таблицы:

FROM materials_students
LEFT JOIN students ON materials_students.student_id = students.id
LEFT JOIN company_profiles ON students.company_profile_id = company_profiles.id
LEFT JOIN companies ON company_profiles.company_id = companies.id
WHERE materials_students.finished_at IS NOT NULL
GROUP BY YEAR, MONTH
ORDER BY YEAR, MONTH

Спасибо!

1 Ответ

0 голосов
/ 04 марта 2020

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

select
  ISNULL(M.yy, C.yy) [yy],
  ISNULL(M.mm, C.mm) [mm], 
  ISNULL(number_material_students, 0) [number_material_students],
  ISNULL(number_components_students, 0) [number_component_students]
from (
  SELECT
    year(materials_students.finished_at) yy, 
    month(materials_students.finished_at) mm,
    count(*) number_material_students
  FROM materials_students
  LEFT JOIN students ON materials_students.student_id = students.id
  LEFT JOIN company_profiles ON students.company_profile_id = company_profiles.id
  LEFT JOIN companies ON company_profiles.company_id = companies.id
  WHERE materials_students.finished_at IS NOT NULL
  GROUP BY year(materials_students.finished_at), month(materials_students.finished_at)
) M
full outer join (
  SELECT
    year(components_students.finished_at) yy, 
    month(components_students.finished_at) mm,
    count(*) number_material_students
  FROM components_students
  LEFT JOIN students ON components_students.student_id = students.id
  LEFT JOIN company_profiles ON students.company_profile_id = company_profiles.id
  LEFT JOIN companies ON company_profiles.company_id = companies.id
  WHERE components_students.finished_at IS NOT NULL
  GROUP BY year(materials_students.finished_at), month(materials_students.finished_at)
) C
ON C.yy = M.yy AND C.mm = M.mm
ORDER BY 1, 2

Я должен был сделать FULL OUTER JOIN между подзапросами, потому что, возможно, были года / месяцы, которые появляются только для материалов, но не для компонентов, и наоборот.

Для извлечения года я использую функцию ISNULL(), поэтому, если год не заполнен из подзапроса материалов, я использую его из подзапроса компонентов , Аналогичные рассуждения применимы ко всем остальным результирующим столбцам.

...