2010-05-27 2 views
12

У меня есть 2 стола: участники и комментарии. Я выбираю всех участников, а затем присоединяюсь к комментариям. Но в комментариях я выбираю несколько СУММ точек, и если пользователь никогда не комментирует, я не могу получить этого пользователя в списке ?!MySql выбирает значение по умолчанию, если результатов нет?

Так как выбрать значение по умолчанию для SUM быть 0, если пользователь не заметил, или некоторые другие решения:

SELECT c.comment_id AS item_id, m.member_id AS member_id, m.avatar, 
      SUM(c.vote_value) AS vote_value, SUM(c.best) AS best, 
      SUM(c.vote_value) + SUM(c.best)*10 AS total 
      FROM members m 
      LEFT JOIN comments c ON m.member_id = c.author_id 
      GROUP BY c.author_id 
      ORDER BY m.member_id DESC 
      LIMIT 0, 20 

EDIT:

Я попытаюсь объяснить .. Итак, есть 2 таблицы, участники и комментарии. Мне нужен список всех пользователей с рейтингом. Комментарии содержат все голоса и лучшие ответы.

Итак, мне нужен листинг всех пользователей, и они забивают.

Пользователи таблица:

member_id - username - avatar 

Комментарии таблица

comment_id - author_id - vote_value - best (0 OR 1) 

попытался также выбрать из КОММЕНТАРИЕВ и присоединиться к членам, но то же самое еще раз :(

+0

Можете ли вы предоставить некоторые примерные данные с ожидаемым выходом? Я не использую MySQL, поэтому, возможно, у них есть синтаксис ярлыков, но вы GROUPing только в одном столбце, но имеете несколько неагрегированных столбцов в вашем SELECT –

+0

@Tom H .: MySQL фактически разрешает этот синтаксис: [GROUP BY и HAVING with Hidden Columns] (http://dev.mysql.com/doc/refman/5.0/ru/group-by-hidden-columns.html). –

+0

Спасибо, Питер. Я знал, что хотя бы одна из основных РСУБД разрешала это, но не могла вспомнить, что именно. Так как это допускает «нелогичные» группировки, это может привести к «отсутствующим» данным, потому что «при использовании этой функции все строки в каждой группе должны иметь одинаковые значения для столбцов, которые исключены из части GROUP BY. для возврата любого значения из группы, поэтому результаты неопределены, если все значения не совпадают ». c.comment_id не всегда может быть одинаковым для данного c.author_id –

ответ

18

Я не уверен, почему вы включаете comment_id в свой список SELECT, если хотите только пользователей и их ранжирование. Вы хотите только их рейтинг по этому конкретному комментарию? Я дам решение сейчас, что предполагает, что вы просто хотите полный список участников с рейтингом:

SELECT 
    M.member_id, 
    M.user_id, 
    M.avatar, 
    COALESCE(SUM(C.vote_value), 0) AS vote_value_sum, 
    COALESCE(SUM(C.best), 0) AS best_sum, 
    COALESCE(SUM(C.vote_value), 0) + SUM(C.best) * 10 AS total_value 
FROM 
    Members M 
LEFT OUTER JOIN Comments C ON 
    C.author_id = M.member_id 
GROUP BY 
    M.member_id 
ORDER BY 
    total_value DESC 
LIMIT 0, 20 

(это предполагает, что vote_value и Лучшие являются NOT NULL столбцы или что MySQL будет игнорировать тех, при вычислении значения SUM - I полагаю, что это так, но я не тестировал это)

-1

Вы можете использовать оператор if для преобразования NULL в 0

SELECT c.comment_id AS item_id, ... 
    IF(SUM(c.vote_value) is null, 0, SUM(c.vote_value)) as vote_value 
FROM members m 
LEFT JOIN comments c ON ... 
+1

COALESCE делает то же самое, но проще. SUM (COALESCE (c.vote_value, 0)) – nathan

+1

Это неуклюжий механизм для этого. 'IF (x is NULL, y, x)' не очень аккуратно. –

+0

@nathan: не знал этого раньше, но просто использовал его. Спасибо (кстати, мне пришлось использовать COALESCE (SUM (col), 0), потому что другой путь еще не вернулся. –

6

Я использую COALESCE для такого рода вещей.

http://dev.mysql.com/doc/refman/5.1/en/comparison-operators.html#function_coalesce

Я хотел бы переписать свои вторые и третьи линии, как:

COALESCE(SUM(c.vote_value), 0) AS vote_value, COALESCE(SUM(c.best),0) AS best, 
COALESCE(SUM(c.vote_value), 0) + COALESCE(SUM(c.best),0) * 10 AS total 
+0

Еще нет всех пользователей: \ – Kenan

-1

Вы могли бы посмотреть на заявление СЛУЧАЯ, тоже: http://dev.mysql.com/doc/refman/5.0/en/case-statement.html

В вашем случае результат будет похожие на ...

SELECT c.comment_id AS item_id, m.member_id AS member_id, m.avatar, 
     (CASE SUM(c.vote_value) WHEN NULL THEN 0 
     ELSE SUM(c.vote_value) END) AS vote_value, SUM(c.best) AS best, 
     (CASE SUM(c.vote_value) + SUM(c.najbolji)*10 WHEN null THEN 0 
     ELSE SUM(c.vote_value) + SUM(c.najbolji)*10 END) AS total 
     FROM members m 
     LEFT JOIN comments c ON m.member_id = c.author_id 
     GROUP BY c.author_id 
     ORDER BY m.member_id DESC 
     LIMIT 0, 20 
+0

Это, к сожалению, неудобно. –

18

MySQ L имеет оператор IFNULL, который позволяет вернуть значение, отличное от нуля, если результат равен нулю.

SELECT c.comment_id AS item_id, m.member_id AS member_id, m.avatar, 
      SUM(IFNULL(c.vote_value, 0)) AS vote_value, SUM(IFNULL(c.best, 0)) AS best, 
      SUM(IFNULL(c.vote_value, 0)) + SUM(IFNULL(c.best, 0))*10 AS total 
      FROM members m 
      LEFT JOIN comments c ON m.member_id = c.author_id 
      GROUP BY c.author_id 
      ORDER BY m.member_id DESC 
      LIMIT 0, 20 

Как уже упоминалось, COALESCE делает что-то подобное (а также работает в MySQL).

+0

Это, наверное, немного лучше, чем 'COALESCE 'для случая желаемого значения по умолчанию. –

+0

Также нет всех пользователей в списке: \ – Kenan

+0

Тогда очень вероятно, что @nathan верен. Попробуйте сгруппировать на m.member_id вместо c.author_id, чтобы узнать, помогает ли это. –

2

Я не думаю, что проблема SUM является проблемой. Я думаю, это может быть ваш

GROUP BY c.author_id 

, где вы группируете по правой стороне левого внешнего соединения. Я не уверен, что это делает, когда правой стороны не существует, но я предполагаю, что это не то, что вы действительно хотите. Скорее всего, вы должны группировать что-то в членах, а не комментарии.

Сказав это, да, вы также должны использовать COALESCE или IFNULL, чтобы превратить нулевые значения в 0.

+0

Пробовал сгруппированием m.member_id, но все тот же, не все пользователи в листинге. Я редактировал свой вопрос со структурами таблиц, возможно, это поможет лучше понять. Спасибо – Kenan

+0

Попытайтесь сломать свой запрос и построить его обратно, чтобы посмотреть, какая часть его сломала. Начните с «SELECT m.member_» id, SUM (c.vote_value) FROM ... ", чтобы убедиться, что это работает, а затем добавьте другие SUM и столбцы по одному, чтобы найти проблему. – nathan