2013-09-01 1 views
2

У меня есть SUM(value), который подсчитывает голоса за каждый idea, но на это влияет сумма tag с каждой идеей.Группа MySQL, воздействуя на другую группу

Например,

SELECT 
    id, 
    title, 
    description, 
    COALESCE(SUM(case when value > 0 then value end),0) votes_up, 
    COALESCE(SUM(case when value < 0 then value end),0) votes_down, 
    GROUP_CONCAT(DISTINCT tags.name) AS 'tags', 
FROM ideas 
LEFT JOIN votes ON ideas.id  = votes.idea_id 
LEFT JOIN tags_rel ON ideas.id  = tags_rel.idea_id 
LEFT JOIN tags  ON tags_rel.tag_id = tags.id 
GROUP BY ideas.id 

Так что, если есть более чем один tags.name, то SUM() умножается на число tags.name

Как я могу это исправить?

+0

Каждый другой СУБД будет отклонять это заявление. Прочтите этот http://rpbouman.blogspot.de/2007/05/debunking-group-by-myths.html и этот http://www.mysqlperformanceblog.com/2006/09/06/wrong-group-by-makes Ваши запросы-хрупкие/чтобы понять, что не так с вашим использованием 'group by'. –

ответ

1

Если вы не хотите, чтобы ваши SUM поражаются tags, вы не должны включать в себя tags в вашем SUM запросе.

Я думаю, вы можете разделить свой запрос на 2 части (запрос внутри запроса). Во-первых, чтобы SUM без идей, то РЕГИСТРИРУЙТЕСЬ идеи данные результата базы на первой части

Что-то хотел (извините, но я не проверял мой запрос, но пока эта идея нравится):

SELECT 
    t.id, 
    t.title, 
    t.description, 
    t.votes_up, 
    t.votes_down, 
    GROUP_CONCAT(DISTINCT tags.name) AS 'tags', 

FROM 
(
    SELECT 
    id, 
    title, 
    description, 
    COALESCE(SUM(case when value > 0 then value end),0) votes_up, 
    COALESCE(SUM(case when value < 0 then value end),0) votes_down, 
    FROM ideas 
    LEFT JOIN votes ON ideas.id  = votes.idea_id 
    GROUP BY ideas.id 
) as t 
LEFT JOIN tags_rel ON t.id  = tags_rel.idea_id 
LEFT JOIN tags  ON tags_rel.tag_id = tags.id 

Надеюсь, что эта помощь

+0

Спасибо! Получил его для работы с использованием подзапроса '=)' – ahren

1
SELECT 
    ideas.id, 
    title, 
    description, 
    COALESCE(SUM(case when value > 0 then value end),0)*t2.cnt votes_up, 
    COALESCE(SUM(case when value < 0 then value end),0)*t2.cnt votes_down, 
    GROUP_CONCAT(DISTINCT tags.name) AS 'tags' 
FROM ideas 
LEFT JOIN votes ON ideas.id  = votes.idea_id 
LEFT JOIN tags_rel ON ideas.id  = tags_rel.idea_id 
LEFT JOIN tags  ON tags_rel.tag_id = tags.id 
LEFT JOIN (SELECT idea_id, COUNT(*) AS cnt 
      FROM tags_rel 
      GROUP BY tags_rel.idea_id) t2 ON ideas.id = t2.idea_id 
GROUP BY ideas.id 

см SQLFIDDLE

EDIT:

С тегами количество столбцов, включенных в результате:

Results:

| ID | TITLE | DESCRIPTION | VOTES_UP | VOTES_DOWN |     TAGS | TAGS_COUNT | 
|----|--------|-------------|----------|------------|-------------------------|------------| 
| 1 | TITLE1 |  DESC1 |  12 |   -4 |    tags1,tags2 |   2 | 
| 2 | TITLE2 |  DESC2 |  18 |   0 |  tags4,tags5,tags3 |   3 | 
| 3 | TITLE3 |  DESC3 |  0 |  -16 | tags9,tags7,tags8,tags6 |   4 | 
| 4 | TITLE4 |  DESC4 |  1 |   0 |     tags10 |   1 | 
+0

Может быть, '* t2.cnt' не там, где вы хотите :) –

+0

Ваши голоса по-прежнему умножаются на количество тегов. Например, в вашем 'idea.id = 3' вы получили только один голос« -1 », но данные показывают« -16 » – ahren

+0

Может быть, это мои тестовые данные или другая часть вашей логики, но посмотрите на это [SQLFIDDLE] (http://www.sqlfiddle.com/#!2/e02df1/16/0), и вы увидите, что '* t2.cnt' содержит правильное количество тегов. Поэтому просто добавьте 'LEFT JOIN (SELECT idea_id, COUNT (*) AS cnt FROM tags_rel GROUP BY tags_rel.idea_id) t2 ON ideas.id = t2.idea_id' и добавьте' * t2.cnt', где вам нужно поставить его в вашем собственном коде –

Смежные вопросы