Преобразование выбора MySQL в PostgreSQL - PullRequest
14 голосов
/ 30 июня 2009

У меня есть этот запрос, который работает правильно в MySQL. Больше информации об этом здесь .

SELECT c.*, SUM(ABS(v.vote)) AS score
FROM categories c,items i, votes v
    WHERE c.id = i.category_id
    AND i.id = v.voteable_id
    AND v.created_at > '#{1.week.ago}'
GROUP BY c.id
ORDER BY score DESC LIMIT 8;

Я попытался запустить его в PostgreSQL, но это сообщение об ошибке не получилось.

PGError: ОШИБКА: столбец "c.name" должен появится в предложении GROUP BY или будет используется в статистической функции

Я не был уверен, что это значит, поэтому я попытался изменить «c.id» на «c.name» в выражении group by (оба работают в MySQL одинаково, предполагая, что имя элемента уникально).

Однако, это просто вызвало еще одну похожую ошибку

PGError: ОШИБКА: столбец "c.id" должен появится в предложении GROUP BY или будет используется в статистической функции

Как решить эту проблему?

Ответы [ 3 ]

11 голосов
/ 30 июня 2009

Вы должны перечислить имена столбцов в SELECT, в которые вы группируете:

SELECT c.id, c.name, SUM(ABS(v.vote)) AS score
FROM categories c,items i, votes v
  WHERE c.id = i.category_id
  AND i.id = v.voteable_id
  AND v.created_at > '#{1.week.ago}'
GROUP BY c.id, c.name
ORDER BY score DESC LIMIT 8;

"Недопустимо включать в предложение SELECT имена столбцов, на которые нет ссылок в предложении GROUP BY."

8 голосов
/ 30 июня 2009

Я только что столкнулся с этой проблемой, но переходил с MySQL на SQL Server. Я подумал, что то, что это разрешено, было странно!

Да, в большинстве баз данных, когда у вас есть предложение GROUP BY, вы можете выбирать только агрегаты столбцов или столбцов, которые появляются в предложении GROUP BY. Это связано с тем, что он не может знать, являются ли другие выбранные вами столбцы действительно уникальными или нет.

Просто поместите нужные столбцы в GROUP BY, если они действительно уникальны. Это была «особенность» MySQL, которая была сомнительной.

Вы можете прочитать о поведении MySQL и его различиях здесь .

Пример:

SELECT c.*, SUM(ABS(v.vote)) AS score
FROM categories c,items i, votes v
    WHERE c.id = i.category_id
    AND i.id = v.voteable_id
    AND v.created_at > '#{1.week.ago}'
GROUP BY c.id, c.name, c.whatever_else
ORDER BY score DESC LIMIT 8;
2 голосов
/ 30 июня 2009

Если вы измените свое утверждение на это, оно должно работать:

SELECT c.id, SUM(ABS(v.vote)) AS score
FROM categories c,items i, votes v
  WHERE c.id = i.category_id
  AND i.id = v.voteable_id
  AND v.created_at > '#{1.week.ago}'
GROUP BY c.id
ORDER BY score DESC LIMIT 8;

Я не уверен, что MySQL дает в результате, но чтобы дать вам очень маленький пример того, почему это не работает в PostgreSQL, взгляните на следующую таблицу categories:

id | name
---|-----
 1 | ABC
 1 | DEF

Вы группируете по id, поэтому каждая строка в результате должна содержать только одну id. Если вы выберите name также, без группировки по нему, что должно быть показано в результате для name?

Это может быть либо ABC, либо DEF, но движок базы данных не может действительно решить это за вас (хотя MySQL, очевидно, и так).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...