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') %>
Ответы
Ответ 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
Вы также можете использовать различные функции окна в соответствии с вашими требованиями.