Проблема PostgreSQL DISTINCT: работает локально, но не на сервере - PullRequest
0 голосов
/ 22 июля 2011

Я столкнулся с неприятной проблемой с запросом PostgreSQL.Это работает в моей локальной среде разработки:

SELECT distinct (user_id) user_id, created_at, is_goodday 
FROM table 
WHERE ((created_at >= '2011-07-01 00:00:00') AND user_id = 95 
AND (created_at < '2011-08-01 00:00:00')) 
ORDER BY user_id, created_at ASC;

... но выдает следующую ошибку на моем сервере QA (который находится на Heroku):

PGError: ERROR:  syntax error at or near "user_id"
LINE 1: SELECT distinct (user_id) user_id, created_at,
                                  ^ 

Почему это может быть?

Другая, возможно, релевантная информация:

Я пробовал заключать в одинарные и двойные кавычки имена полей

Это приложение на Rails 3, но я использую этот SQL-кодт.е. ActiveRecord magic

Моя локальная версия Postgres на Mac - 9.0.4, но я понятия не имею, какую версию Heroku использует

Ответы [ 3 ]

1 голос
/ 23 июля 2011

Согласно вашему комментарию, стандартная версия PostgreSQL этого запроса будет:

SELECT user_id, created_at, is_goodday
FROM table
WHERE created_at >= '2011-07-01 00:00:00'
  AND created_at <  '2011-08-01 00:00:00'
  AND user_id     = 95
ORDER BY created_at DESC, id DESC
LIMIT 1

Вам не нужно user_id в ORDER BY, потому что у вас есть user_id = 95, вы хотите created_at DESC в ORDER BY поставить самый последний created_at вверху;затем вы LIMIT 1 отрежете только первую строку в наборе результатов.GROUP BY может использоваться для обеспечения уникальности или если вам нужно сгруппировать вещи для агрегатной функции, но вам она не нужна ни для одной из перечисленных здесь функций, поскольку вы можете получить уникальность с помощью ORDER BY и LIMIT, и вы можете скрыть агрегирование внутриORDER BY (то есть вам не нужен MAX, потому что ORDER BY делает это за вас).

Так как в вашем WHERE есть user_id = 95, вам не нужно user_id в SELECT, но вы можете оставитьесли это облегчает вам работу в Ruby-стране.

Возможно, у вас может быть несколько записей с одним и тем же created_at, поэтому я добавил id DESC в ORDER BY, чтобы заставить PostgreSQLвыберите самый высокий id.Нет ничего плохого в том, чтобы быть параноиком, когда они действительно хотят вас поймать, а ошибки определенно есть.

Кроме того, вы хотите, чтобы DESC в вашем ORDER BY получало самые высокие значения в верхней части, ASC ставит самые низкие значения сверху.Более поздние отметки времени будут выше.

В общем случае GROUP BY и SELECT должны совпадать, потому что:

Когда присутствует GROUP BYнедопустимо, чтобы выражения списка SELECT ссылались на несгруппированные столбцы, кроме как в агрегатных функциях, так как было бы более одного возможного значения для несгруппированного столбца.

Но это не такдело здесь, потому что вам совсем не нужен GROUP BY.Я связался с версией документации 8.3 для соответствия используемой вами версии PostgreSQL.

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

0 голосов
/ 22 июля 2011

Вы используете DISTINCT ON (без записи ON).Возможно, вам следует написать ON.Возможно, ваш сервер postgres датируется до того, как эта функция была реализована (а это уже довольно старая версия).

Если ничего не помогает, вы всегда можете сделать это с помощью некоторого GROUP BY ...

0 голосов
/ 22 июля 2011

вставьте цитату в user_id как user_id = '95'.Ваш запрос должен быть

SELECT distinct (user_id) as uid, created_at, is_goodday  FROM table  WHERE 
((created_at >= '2011-07-01 00:00:00') AND user_id = '95'  AND (created_at < '2011-08-01 00:00:00'))  ORDER BY user_id, created_at ASC;   
...