MySql - Sql-запрос или процедура для генерации отчета путем транспонирования строк в столбцы - PullRequest
0 голосов
/ 12 марта 2012

Это первый раз - я пытаюсь сделать что-то подобное - так что, пожалуйста, потерпите меня.Это на MySql.

Я пытаюсь создать отчет, чтобы узнать, какие студенты закончили какие темы и на какие даты.

Это текущий запрос, который я выполняю

select u.email,t.topic_name,tu.date_created as 'date completed'
from topic_user tu
join topic t ON tu.topic_id = t.topic_id
join user u ON tu.user_id = u.user_id

, который будет возвращать результаты наподобие

email         |    topic_name      |    date completed
abc@gmail.com |    ABC             |    03/01/2012
abc@gmail.com |    DEF             |    03/02/2012
abc@gmail.com |    ABC             |    03/08/2012
abc@gmail.com |    GHI             |    03/08/2012
def@gmail.com |    ABC             |    03/02/2012
def@gmail.com |    XYZ             |    03/10/2012

Чтобы создать отчет, нужно иметь имена тем в качестве заголовков столбцов и дату, когда они завершили его в виде значений

email         |    ABC      |    DEF      |    GHI      |    JKL      |    XYZ     
abc@gmail.com | 03/08/2012  | 03/02/2012  | 03/08/2012  |    null     |    null
def@gmail.com | 03/02/2012  |    null     |    null     |    null     |  03/10/2012

Несколько вещей, на которые следует обратить внимание:

1) Все названия тем будут взяты из таблицы тем - даже если они не были заполнены учащимися - значение должно быть нулевым

2) В случае студента abc@gmail.com - он дважды изучил тему ABC - но в отчете должна быть указана самая поздняя дата.

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

Буду признателен за любую помощь, которую вы сможете оказать.Большое спасибо

Ответы [ 2 ]

2 голосов
/ 12 марта 2012

Я не проверял это, и мой опыт работы с MySQL ограничен, но я надеюсь, что ниже, что вы ищете.Он динамически создает оператор SELECT с использованием функции GROUP_CONCAT, а затем выполняет его (это бит, который я не уверен в способе сделать это в MySQL).темы не меняются очень регулярно, вы можете просто использовать:

SELECT  Email,
        MAX(CASE WHEN Topic_ID = 1 THEN tu.Date_Created END) AS ABC,
        MAX(CASE WHEN Topic_ID = 2 THEN tu.Date_Created END) AS DEF,
        MAX(CASE WHEN Topic_ID = 3 THEN tu.Date_Created END) AS GHI,
        MAX(CASE WHEN Topic_ID = 4 THEN tu.Date_Created END) AS JKL,
        MAX(CASE WHEN Topic_ID = 5 THEN tu.Date_Created END) AS XYZ
FROM    Topic_User tu
        INNER JOIN users u
            ON u.User_ID = tu.User_ID
GROUP BY Email

и изменять запрос каждый раз, когда добавляется новая тема (это запрос, созданный в процессе выше).

1 голос
/ 12 марта 2012

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

SELECT
    u.email,
    MAX(IF(t.topic_name = 'ABC', tu.date_created, NULL)) AS 'ABC',
    MAX(IF(t.topic_name = 'DEF', tu.date_created, NULL)) AS 'DEF',
    etc
FROM topic_user tu
INNER JOIN topic t
    ON tu.topic_id = t.topic_id
INNER JOIN user u
    ON tu.user_id = u.user_id
GROUP BY u.user_id;

Таким образом, на выбранном вами языке на стороне сервера вы будете динамически создавать список полей на основе первого запроса списка тем.

Вы можете немного сократить накладные расходы на этот запрос, используя topic_ids вместо topic_names, чтобы можно было отбросить объединение в таблице тем -

SELECT
    u.email,
    MAX(IF(tu.topic_id = 1, tu.date_created, NULL)) AS 'ABC',
    MAX(IF(tu.topic_id = 2, tu.date_created, NULL)) AS 'DEF',
    etc
FROM topic_user tu
INNER JOIN user u
    ON tu.user_id = u.user_id
GROUP BY u.user_id;
...