Список преподавателей и их курсов (SQL-запрос)

Список преподавателей и их курсов (SQL-запрос)

от Mikhail Apakin -
Количество ответов: 18

Добрый день!

Я снова с вопросом о запросе. Есть задача — вывести список всех преподавателей системы с их курсами. То есть если у преподавателя 5 курсов — значит, 5 строк. Если у курса 4 преподавателя — значит, 4 строки. Я сделал статистику по курсам, но я смог достать только или каунт преподавателей или их конкат. Сделать так, чтобы на каждого преподавателя каждого курса была отдельная строка, я не сумел.

Вдруг кто-то решал такую задачу? Кстати, стоит configurable reports, но я так и не понял, как его использовать кроме как sql-запросом.

Заранее спасибо.

В ответ на Mikhail Apakin

Re: Список преподавателей и их курсов (SQL-запрос)

от Vadim Tabunshchik -
Изображение пользователя Developers
SELECT
    qq.tmp 'Преподаватель'
   ,qq.course 'Курс'
FROM
(
      SELECT
              CASE
                     WHEN @txt = t.fullname then ''
                     ELSE @txt := t.fullname
              END tmp
             ,t.course
     FROM
         (
           SELECT
                      CONCAT(u.lastname,' ',u.firstname) fullname
                     ,c.fullname course
           FROM
                  mdl_user u
                  JOIN mdl_role_assignments ra ON ra.userid=u.id
                  JOIN mdl_context ctx ON ctx.id = ra.contextid
                  JOIN mdl_course c ON c.id=ctx.instanceid
           WHERE ra.roleid=3
           ORDER BY u.lastname, u.firstname ASC
           ) t,
              (SELECT @txt := '') r
) qq
В ответ на Vadim Tabunshchik

Re: Список преподавателей и их курсов (SQL-запрос)

от Mikhail Apakin -

Спасибо огромное, очень круто, всё работает.

У меня только один вопрос: для чего нужна конструкция 

 (SELECT @txt := '') r

?

Спасибо.

В ответ на Mikhail Apakin

Re: Список преподавателей и их курсов (SQL-запрос)

от Vadim Tabunshchik -
Изображение пользователя Developers
У меня только один вопрос: для чего нужна конструкция 

улыбаюсь

Можно убрать (вместе с запятой впереди), строка осталось с запроса на другую тему, там 3 колонки выводились в результатах

В ответ на Vadim Tabunshchik

Re: Список преподавателей и их курсов (SQL-запрос)

от Vadim Tabunshchik -
Изображение пользователя Developers

Оказалось, в разных оболочках запрос работает по разному.

В Navicat MySQL С/без этой конструкции вывод одинаковый, а вот в report_customsql и phpmyadmin конструкция нужна, иначе название курса выводится в каждой строке, что загромождает таблицу результатов.

В ответ на Vadim Tabunshchik

Re: Список преподавателей и их курсов (SQL-запрос)

от Виталий Лавров -
Изображение пользователя Эксперт по Moodle

Это будет работать только на mysql, т.к. аналога локальных переменных нет в остальных реализациях SQL.

А в configurable_reports нет средств удаления дублирующих значений или группировки по полю ?

В ответ на Виталий Лавров

Re: Список преподавателей и их курсов (SQL-запрос)

от Vadim Tabunshchik -
Изображение пользователя Developers

Запрос и написан под mysql, т.к. в нем нем нет оконных функций типа row_number() over()

Удаление дублирующих значений или группировка приведёт к тому, имхо, что будет выведена только первая строка

Я говорил о том, что в разных прогах  вывод запроса отличается.

Например, в Navicat MySQL строка (SELECT @txt := '') r роли не играет, резалт одинаковый:

со строкой: ris      


без строки: smallicon

А вот в phpmyadmin:

021 и без строки: ris

В ответ на Виталий Лавров

Re: Список преподавателей и их курсов (SQL-запрос)

от Mikhail Apakin -

>> А в configurable_reports нет средств удаления дублирующих значений или группировки по полю?

Есть, но задача ровно противоположная.

В ответ на Vadim Tabunshchik

Re: Список преподавателей и их курсов (SQL-запрос)

от Mikhail Apakin -

Мне и нужно и в каждой строке название курса, и ФИО преподавателя.

Поэтому переменная вообще не нужна, и удалось упростить код.

SELECT
qq.fullname Teacher, qq.course Course FROM ( SELECT CONCAT(u.lastname,' ',u.firstname) fullname ,c.fullname course FROM {user} u JOIN {role_assignments} ra ON ra.userid=u.id JOIN {context} ctx ON ctx.id = ra.contextid JOIN {course} c ON c.id=ctx.instanceid WHERE ra.roleid=3 ORDER BY u.lastname, u.firstname ASC ) qq

В ответ на Mikhail Apakin

Re: Список преподавателей и их курсов (SQL-запрос)

от Vadim Tabunshchik -
Изображение пользователя Developers
и удалось упростить код.

Так оставьте только вложенный селект «SELECT CONCAT(u.lastname,' ',u.firstname) fullname…», зачем тут вообще qq?

В ответ на Mikhail Apakin

Re: Список преподавателей и их курсов (SQL-запрос)

от Mikhail Apakin -

И правда, чего это я. Спасибо.

А я изначально пошёл обратным путём, от таблицы с курсом к таблице с пользователями:

SELECT c.id, c.fullname
,(SELECT GROUP_CONCAT( CONCAT( u.firstname,  " ", u.lastname ) )
FROM {course} ic
JOIN {context} ctx ON ctx.instanceid = ic.id
JOIN {role_assignments} ra ON ctx.id = ra.contextid AND ctx.contextlevel = 50
JOIN {role} r ON ra.roleid = r.id
JOIN {user} u ON u.id = ra.userid
WHERE r.id = 3 AND ic.id = cou.id
GROUP BY ic.id
) AS TeacherNames
FROM {course} c


и не мог понять, как разделить преподавателей.

В ответ на Mikhail Apakin

Re: Список преподавателей и их курсов (SQL-запрос)

от Vadim Tabunshchik -
Изображение пользователя Developers

Таблица {role} вообще не нужна, есть поле role_assignments.roleid

ic.id = cou.id - выдает ошибку, алиас cou откуда взялся?

И последнее - GROUP BY ic.id делать нельзя, выведет только первую строку:

ris

А должно быть так:

smallicon

Вот запрос:

SELECT ic.id, ic.fullname
,CONCAT(u.firstname,' ', u.lastname) TeacherNames
FROM {course} ic
JOIN {context} ctx ON ctx.instanceid = ic.id
JOIN {role_assignments} ra ON ctx.id = ra.contextid AND ctx.contextlevel = 50
JOIN {user} u ON u.id = ra.userid
WHERE ra.roleid = 3
ORDER BY ic.id
В ответ на Vadim Tabunshchik

Re: Список преподавателей и их курсов (SQL-запрос)

от Mikhail Apakin -

>> ic.id = cou.id - выдает ошибку, алиас cou откуда взялся?

c.id, конечно. Но уже вижу, что второе обращение к курсам избыточно.

Спасибо за оптимизированный код, теперь буду учиться выдирать для этой таблицы кол-во ресурсов, элементов и тестовых вопросов. Примерный алгоритм у меня уже в голове есть, осталось его реализовать.


Ещё раз огромное спасибо, вы мне очень помогли.

В ответ на Vadim Tabunshchik

Re: Список преподавателей и их курсов (SQL-запрос)

от Mikhail Apakin -
Извините, пожалуйста, а вы можете мне ещё раз помочь?

В общем, развитие задачи привело к тому, что мне нужно получить список всех преподавателей, у которых есть хотя бы один курс, в котором есть хотя бы один элемент и один ресурс. 

У меня получилось вот так:

SELECT c.id AS No, c.fullname AS kypc
,CONCAT(u.firstname,' ', u.lastname) AS TeacherName
,(SELECT COUNT(*) FROM {course_sections} sec WHERE c.id = sec.course AND sec.sequence!='') AS chapters
,(SELECT COUNT(*) FROM {course_modules} res WHERE c.id = res.course AND res.module IN (20,3,11,8,12,15,17)) AS resourses
,(SELECT COUNT(*) FROM {course_modules} ele WHERE c.id = ele.course AND ele.module IN (1,4,5,6,7,9,10,13,16,18,19,21,22,23,24)) AS elements
FROM {course} c
JOIN {context} ctx ON ctx.instanceid = c.id
JOIN {role_assignments} ra ON ctx.id = ra.contextid AND ctx.contextlevel = 50
JOIN {user} u ON u.id = ra.userid
WHERE ra.roleid = 3
HAVING resourses>0 AND elements>0 AND c.id>1
ORDER BY TeacherName


И всё бы хорошо, но задача пошла дальше — теперь нужно вывести этот же запрос, но имя преподавателя должно быть уникальным, без повторов. Какой при этом попадётся курс — пофиг, любой подходит под  наши условия.

А теперь проблема: GROUP BY TeacherName, так же как и DISTINCT u.id, вставленный после c.id, выдаёт ошибку, совершенно её не объясняя. Syntax error и всё тут. Понятно, что это можно потом сделать, удалив дубли в Excel'е, но хотелось бы это реализовать средствами MySQL. Не подскажете, в какую сторону копать?

Заранее спасибо.

В ответ на Mikhail Apakin

Re: Список преподавателей и их курсов (SQL-запрос)

от Vadim Tabunshchik -
Изображение пользователя Developers
Какой при этом попадётся курс — пофиг, любой подходит под  наши условия.

А чо так? Какой курс и кол-во материалов не интересует? улыбаюсь

Не подскажете, в какую сторону копать?

Вставить GROUP BY TeacherName перед HAVING

В ответ на Vadim Tabunshchik

Re: Список преподавателей и их курсов (SQL-запрос)

от Mikhail Apakin -
А чо так? Какой курс и кол-во материалов не интересует? 

Вообще нет, но в данном случае — да улыбаюсь

Вставить GROUP BY TeacherName перед HAVING

Боже, как просто. Спасибо. А я уже начал обёртки крутить вокруг селекта.

В ответ на Mikhail Apakin

Re: Список преподавателей и их курсов (SQL-запрос)

от Лейли Быстрова -
Здравствуйте, ваш пост очень и очень помог мне решить одну задачу, но сейчас попробую оживить тему...

К выводу курсов я прибавила вывод разделов, в которых эти курсы лежат. Еще заметила, что в таблице mdl.course_categories находится колонка depth и path.
depth показывает количество вложенных категорий друг в друга, а path что-то типа шифра этих категорий. Например, 
path /57/62 имеет значение depth 2. Чем больше вложенность в path, тем больше значение depth... В моем случае path /57/62 - это очная форма обучения (57) и направление менеджмент (62).

Допустим, я хочу показать в отчете еще и колонку, к какому направлению и форме обучения относятся мои курсы. На дальнейшую вложенность (depth должен быть меньше или равен 2) мне все равно. То есть если курс находится ниже /57/62/78/80 (последние 2 цифры в моем случае - профиль и семестр), то в колонке бы прописывалось только очная форма обучения и направление менеджмент. 

Вопрос, как это оформить в коде (я пока ни бум-бум в sql), чтобы вместо course_categories.path /57/62 отображалось в отчете в одной колонке Очная форма в другой вторая цифра - Направление "Менеджмент"?
Я хочу перечислить в отчете нужные мне  path
В моем случае это 
/57/58
/57/59
/57/60
/57/61
/57/62
/57/63
/57/216 /223/224 /223/225 и тд. Но при этом, чтобы эти "патчи" имели вполне "человеческое" название в самом отчете. Вот начала мудрить с вашим кодом, практически без изменений... Буду благодарна за любую наводку.


SELECT c.id AS № , c.fullname AS Курс ,
c.shortname AS краткое ,
CONCAT( u.firstname, ' ', u.lastname ) AS TeacherName,

( SELECT COUNT(*) FROM prefix_course_sections sec WHERE c.id = sec.course AND sec.sequence != '' ) AS chapters,
( SELECT COUNT(*) FROM prefix_course_modules res WHERE c.id = res.course AND res.module IN ( 20, 3, 11, 8, 12, 15, 17 )) AS resourses,
( SELECT COUNT(*) FROM prefix_course_modules ele WHERE c.id = ele.course AND ele.module IN ( 1, 4, 5, 6, 7, 9, 10, 13, 16, 18, 19, 21, 22, 23, 24 )) AS elements,
c.summary AS Описание ,
ct. name AS Направление ,
ct.path AS path,
ct.depth AS DEPTH

FROM prefix_course AS c
JOIN prefix_context AS ctx ON ctx.instanceid = c.id
JOIN prefix_role_assignments AS ra ON ctx.id = ra.contextid AND ctx.contextlevel = 50
JOIN prefix_user AS u ON u.id = ra.userid
INNER JOIN prefix_course_categories AS ct ON ct.id = c.category
WHERE ra.roleid = 3
GROUP BY c.id
HAVING resourses > 0
AND elements > 0
AND № > 1
ORDER BY TeacherName ASC


В итоге хочу добиться что-то типа такого. В моем случае я просто в экселе автозаменой забила pathСкриншот_таблицы