Как группировать итоговые столбцы из разных таблиц? - PullRequest
1 голос
/ 06 июля 2010

У меня есть пользовательская таблица (Пользователь) и 3 учебные таблицы (Текст, Видео и др.).

Каждый учебник имеет столбцы rating_positive и rating_negative и связан с пользователем (id).

Я хочу выбрать 10 пользователей с наибольшим количеством учебных пособий и суммой положительных / отрицательных оценок их учебных пособий.

Я пробовал следующий запрос, но он не работает.Он возвращает слишком много результатов для tutorials_count / pos / neg.Как я могу сделать это правильно?

SELECT  
    u.id AS user_id,  
    (COUNT(t.id) + COUNT(v.id) + COUNT(o.id)) AS tutorials_count,
    (SUM(t.rating_positive) + SUM(v.rating_positive) + SUM(o.rating_positive)) AS pos,
    (SUM(t.rating_negative) + SUM(v.rating_negative) + SUM(o.rating_negative)) AS neg
FROM
    user u LEFT JOIN trick t ON u.id = t.submitter_id
    LEFT JOIN video v ON u.id = v.submitter_id
    LEFT JOIN other o ON u.id = o.submitter_id
GROUP BY u.id
ORDER BY tutorials_count DESC
LIMIT 10

Ответы [ 2 ]

2 голосов
/ 06 июля 2010

Попробуйте создать подзапрос с СОЮЗОМ ВСЕХ трех таблиц, которые вас интересуют, а затем присоединитесь к этому:

SELECT  
    u.id AS user_id,  
    COUNT(submitter_id) AS tutorials_count,
    IFNULL(SUM(rating_positive), 0) AS pos,
    IFNULL(SUM(rating_negative), 0) AS neg
FROM user u
LEFT JOIN (
    SELECT submitter_id, rating_positive, rating_negative FROM trick
    UNION ALL
    SELECT submitter_id, rating_positive, rating_negative FROM video
    UNION ALL
    SELECT submitter_id, rating_positive, rating_negative FROM other
) T1
ON u.id = T1.submitter_id
GROUP BY u.id
ORDER BY tutorials_count DESC
LIMIT 10
1 голос
/ 06 июля 2010

ЛЕВЫЕ СОЕДИНЕНИЯ хороши и будут работать лучше, чем объединение всех трех таблиц перед выполнением агрегации.

Проблема в том, что SUMmation для LEFT JOIN означает, что результатом может быть NULL, который нельзя добавить вместе с суммой из других столбцов. IE:

... SUM(t.rating_positive) + 1

... вернет NULL, если SUM(t.rating_positive) нет подтверждающих записей, потому что NULL + 1 равно NULL.

Вам нужно использовать COALESCE, чтобы преобразовать их в ноль, чтобы математика работала - IFNULL является приемлемой альтернативой, но она специфична для MySQL, поэтому вряд ли будет переносимой:

   SELECT u.id AS user_id,  
          COALESCE(COUNT(t.id), 0) + COALESCE(COUNT(v.id), 0) + COALESCE(COUNT(o.id), 0) AS tutorials_count,
          COALESCE(SUM(t.rating_positive), 0) + COALESCE(SUM(v.rating_positive), 0) + COALESCE(SUM(o.rating_positive), 0) AS pos,
          COALESCE(SUM(t.rating_negative), 0) + COALESCE(SUM(v.rating_negative), 0) + COALESCE(SUM(o.rating_negative), 0) AS neg
     FROM USER u 
LEFT JOIN trick t ON u.id = t.submitter_id
LEFT JOIN video v ON u.id = v.submitter_id
LEFT JOIN other o ON u.id = o.submitter_id
 GROUP BY u.id
 ORDER BY tutorials_count DESC
    LIMIT 10
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...