2009-07-16 1 views
0

Короче говоря, какие поля следует поместить после предложения GROUP BY?какие столбцы помещать в MySQL GROUP BY статья

SELECT questions.question_id, questions.title, questions.content, questions.view_count, questions.posted_on, users.user_id, users.group_id, users.username, users.first_name, users.last_name COUNT(answers.answer_id) AS answer_count 
FROM (questions) 
JOIN answers ON questions.question_id = answers.question_id 
JOIN users ON questions.user_id = users.user_id 
WHERE `questions`.`publish` = 'Y' AND `questions`.`deleted_at` IS NULL AND `users`.`blocked` = 'N' 
GROUP BY questions.question_id 

Должен ли я помещать все неагрегированные поля, упомянутые в SELECT, или только один из них в порядке? (например, just question_id) Я запутался, потому что в любом случае результаты одинаковы. В чем разница ?

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

обновление: ОК, похоже, что я должен положить все, чтобы получить точный результат. Это вызвало другие вопросы: насколько точна точность? Разве это не будет хорошо? Как насчет влияния на производительность?

ответ

1

«Вы должны поместить все не agregated столбцы для точного результата»

Правда, но я бы добавил, что вы поместили все столбцы в том порядке, в котором вы хотите, чтобы он был сгруппирован (что может быть важно для вас?).

Редактировать: Точный означает, что если вы этого не сделаете, ваш запрос просто потерпит крах. Что касается выступлений, тем больше полей у вас в GROUP BY, тем больше ваши выступления уменьшаются, но это не удивительно.

1

Для точного результата вам необходимо поместить все неагрегированные столбцы.

+0

Насколько точна точность? Разве это не будет хорошо? Как насчет влияния на производительность? – andyk

0

и должно сделать: GROUP BY questions.question_id, questions.title, questions.content, questions.view_count, questions.posted_on, users.user_id, users.group_id, users.username, users.first_name, users.last_name

(то есть. все из них)

или

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

EDIT: вот пример второго варианта (не проверял, но должно работать)

SELECT questions.question_id, questions.title, questions.content, questions.view_count, questions.posted_on, users.user_id, users.group_id, users.username, users.first_name, users.last_name, r.AN_ANSWER_COUNT 
FROM (questions q) 
JOIN answers ON questions.question_id = answers.question_id JOIN users ON questions.user_id = users.user_id 

left join (SELECT question_id, COUNT(a.answer_id) AS AN_ANSWER_COUNT 
        FROM answers a 

        WHERE (your_condition) 
        GROUP BY question_id)r 
      on q.question_id = a.question_id 

WHERE `questions`.`publish` = 'Y' AND `questions`.`deleted_at` IS NULL AND `users`.`blocked` = 'N' 
+0

не могли бы вы подробнее остановиться на альтернативе внутреннего соединения? – andyk

+0

Трюк с ним (проблемы с псевдонимами), и у меня он работает, но он берет запись вопроса для каждого ответа (11 вопросов * 36 ответов на 396 записей). Или я понял это неправильно? – andyk

+0

извините ... маленькая ошибка: где я писал: на q.question_id = a.question_id это должно быть q.question_id = r.question_id – waqasahmed

1

MySQL получает обе опции, другие базы данных этого не делают. Другие базы данных (hsqldb, Oracle) заставят вас поместить все поля, выбранные в предложение GROUP BY. Когда каждый кладет все столбцы после предложения GROUP BY, результат обычно менее неоднозначен. MySQL «интерпретирует» ваш запрос как:

SELECT questions.question_id, FIRST_VALUE(questions.title), FIRST_VALUE(questions.content), FIRST_VALUE(questions.view_count), FIRST_VALUE(questions.posted_on), FIRST_VALUE(users.user_id), FIRST_VALUE(users.group_id), FIRST_VALUE(users.username), FIRST_VALUE(users.first_name), FIRST_VALUE(users.last_name) COUNT(answers.answer_id) AS answer_count 
FROM (questions) 
JOIN answers ON questions.question_id = answers.question_id 
JOIN users ON questions.user_id = users.user_id 
WHERE `questions`.`publish` = 'Y' AND `questions`.`deleted_at` IS NULL AND `users`.`blocked` = 'N' 
GROUP BY questions.question_id 

То есть, если MySQL имеет функцию «FIRST_VALUE».

Поскольку вы группируете уникальный идентификатор (questions.question_id), результаты совпадают. Если один из групп отличается от уникального идентификатора, возвращаемые значения очень неоднозначны.

Единственное, что я не уверен, - это то, что более эффективно выполнять группу в соответствии с одним полем. Я предполагаю, что БД достаточно умны, чтобы понять, что вы группируетесь по уникальному идентификатору и планируете выполнение соответственно, но я не уверен.

Если нет никакой разницы в эффективности - вы должны поместить все поля после GROUP BY, потому что это более стандартно. В противном случае решите, предпочитаете ли вы писать стандартный SQL над написанием эффективного SQL.