Подтвердить что ты не робот

PG:: Ошибка: SELECT DISTINCT, ORDER BY выражения должны появиться в списке выбора

ActionView:: Template:: Error (PG:: Error: ERROR: для SELECT DISTINCT, ORDER BY выражения должны появляться в списке выбора

Я создаю веб-сайт событий, и я пытаюсь сортировать обработанные rsvps по времени начала события. Есть много RSVPS, поэтому я группирую их с четкими, но за последние несколько дней у меня была большая сложность при сортировке результатов без появления этой ошибки на PG. Я рассмотрел некоторые из предыдущих вопросов по этой теме и все еще довольно потерян. Как я могу заставить это работать? Большое вам спасибо!

@rsvps = Rsvp.where(:voter_id => current_user.following.collect {|f| f["id"]}, :status => 'going').where("start_time > ? AND start_time < ?", Time.now, Time.now + 1.month).order("count_all desc").count(:group => :event_id).collect { |f| f[0] }

<%= render :partial => 'rsvps/rsvp', :collection => Rsvp.where(:event_id => @rsvps).select("DISTINCT(event_id)").order('start_time asc') %>
4b9b3361

Ответ 1

Предложение ORDER BY может применяться только после применения DISTINCT. Поскольку для операций DISTINCT учитываются только поля в инструкции SELECT, это единственные поля, которые могут использоваться в ORDER BY.

Логически, если вам нужен только отдельный список значений event_id, то какой порядок он должен иметь, должен быть неактуальным. Если порядок имеет значение, вы должны добавить start_time в список SELECT, чтобы существовал контекст для заказа.

Кроме того, эти два предложения SELECT НЕ эквивалентны, поэтому будьте осторожны:

SELECT DISTINCT(event_id, start_time) FROM ...

SELECT DISTINCT event_id, start_time FROM ...

Вторая форма, которую вы хотите. Первый будет возвращать серию записей с данными, представленными как конструкцией ROW (один столбец с кортежем внутри). Второй возвращает нормальные столбцы вывода данных. Он работает только так, как ожидалось, в случае с одним столбцом, где структура ROW уменьшается, поскольку это только один столбец.

Ответ 2

Я знаю, что это довольно старый вопрос, но я просто просмотрел небольшой пример в моей голове, который помог мне понять, почему Postgres имеет это кажущееся странным ограничение на столбцы SELECT DISTINCT/ORDER BY.

Представьте, что в вашей таблице Rsvp есть следующие данные:

 event_id |        start_time
----------+------------------------
    0     | Mar 17, 2013  12:00:00
    1     |  Jan 1, 1970  00:00:00
    1     | Aug 21, 2013  16:30:00
    2     |  Jun 9, 2012  08:45:00

Теперь вы хотите получить список отдельных event_ids, упорядоченных по их началу. Но куда идти 1 идти? Должен ли он быть первым, потому что один кортеж начинается 1 января 1970 года, или он должен идти последним из-за 21 августа 2013 года?

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

Что касается фактического вопроса - альтернатива ответом Мэтью заключается в использовании агрегатной функции типа MIN или MAX для сортировки:

  SELECT event_id
    FROM Rsvp
GROUP BY event_id
ORDER BY MIN(start_time)

Явная группировка и агрегация на start_time позволяют базе данных выступить с однозначным упорядочением кортежей результатов. Обратите внимание, однако, что читаемость определенно является проблемой в этом случае;)

Ответ 3

Поскольку вы используете столбец start_time, вы можете использовать row_number(), который является одной из оконных функций PostgreSQL, и поместить его в

  • Порядок start_time, если вы ожидаете значения строки с первым start_time

    Выберите event_id из (ВЫБРАТЬ event_id, ROW_NUMBER() OVER (PARTITION BY event_id ORDER BY start_time) КАК first_row ОТ Rsvp), где first_row = 1

  • обратный порядок start_time, если вы ожидаете значения строки с последним start_time

    Выберите event_id из (ВЫБЕРИТЕ event_id, ROW_NUMBER() OVER (PARTITION BY event_id ORDER BY start_time desc) AS last_row FROM Rsvp), где last_row = 1

Вы также можете использовать различные функции окна в соответствии с вашими требованиями.