Я хочу выполнить этот запрос:
SELECT DISTINCT ON (address_id) purchases.address_id, purchases.*
FROM purchases
WHERE purchases.product_id = 1
ORDER BY purchases.purchased_at DESC
Но я получаю эту ошибку:
PG :: Ошибка: ОШИБКА: выражения SELECT DISTINCT ON должны соответствовать начальным выражениям ORDER BY
Добавление в address_id
качестве первого ORDER BY
выражения заглушает ошибку, но я действительно не хочу добавлять сортировку address_id
. Можно ли обойтись без заказа по address_id
?
sql
postgresql
sql-order-by
distinct-on
sl_bug
источник
источник
Ответы:
Документация гласит:
Официальная документация
Так что вам придется добавить
address_id
в заказ по.В качестве альтернативы, если вы ищете полную строку, содержащую самый последний приобретенный продукт для каждого
address_id
и отсортированный результат,purchased_at
то вы пытаетесь решить проблему наибольшего N на группу, которая может быть решена с помощью следующих подходов:Общее решение, которое должно работать в большинстве СУБД:
Более ориентированное на PostgreSQL решение, основанное на ответе @ hkf:
Здесь проблема прояснена, расширена и решена: выбор строк, упорядоченных по одному столбцу и отличающихся по другому
источник
SELECT DISTINCT ON (purchases.purchased_at, address_id)
. Однако две записи с одним и тем же address_id, но разными значениями приобрела в результате будут получены дубликаты в возвращенном наборе. Убедитесь, что вы осведомлены о данных, которые запрашиваете.Вы можете упорядочить по address_id в подзапросе, затем упорядочить по желанию во внешнем запросе.
источник
select
, я не думаю, что это рабочий код?address_id
дважды (без необходимости). У многих клиентов возникают проблемы с повторяющимися именами столбцов.ORDER BY address_id DESC
бессмысленно и вводит в заблуждение. Ничего полезного в этом запросе нет. Результатом является произвольный выбор из каждого набора строк с одинаковымиaddress_id
, а не строки с самой последнейpurchased_at
. Неоднозначный вопрос явно не задавался этим, но это почти наверняка намерение ОП. Короче говоря: не используйте этот запрос . Я разместил альтернативы с объяснением.Подзапрос может решить:
Начальные выражения в
ORDER BY
должны согласовываться со столбцами вDISTINCT ON
, так что вы не можете упорядочить по разным столбцам в одномSELECT
.Используйте дополнительный
ORDER BY
в подзапросе, только если вы хотите выбрать конкретную строку из каждого набора:Если
purchased_at
можноNULL
, посмотримDESC NULLS LAST
. Но убедитесь, что ваш индекс совпадает, если вы собираетесь его использовать. Видеть:Связанные с более подробным объяснением:
источник
DISTINCT ON
без соответствияORDER BY
. Первый запрос требуетORDER BY address_id
внутри подзапроса.DISTINCT ON
безORDER BY
в том же запросе. В этом случае вы получаете произвольную строку из каждого набора пиров, определенных вDISTINCT ON
предложении. Попробуйте или перейдите по ссылкам выше для получения подробной информации и ссылок на руководство.ORDER BY
в том же запросе (тот жеSELECT
) просто не может не согласитьсяDISTINCT ON
. Я тоже это объяснил.ORDER BY
не видел смысла примечания «непредсказуемый, если не используется» в документах, потому что для меня не имеет смысла, что эта функция реализована так, чтобы иметь возможность обрабатывать непоследовательные наборы значений ... но не позволит вам использовать это с явным порядком. Раздражает.DISTINCT ON
выражениям (пока).Оконная функция может решить это за один проход:
источник
address_id
. Принцип может работать, хотя. Связанные примеры: stackoverflow.com/a/22064571/939860 или stackoverflow.com/a/11533808/939860 . Но есть более короткие и / или более быстрые запросы для решения проблемы.Для тех, кто использует Flask-SQLAlchemy, это работает для меня
источник
query.distinct(foo).from_self().order(bar)
Purchases.query
?Вы также можете сделать это с помощью предложения group by
источник
purchases
только нет двух столбцовaddress_id
иpurchased_at
). Из-заGROUP BY
этого вам нужно будет использовать статистическую функцию, чтобы получить значение каждого столбца, не используемого для группировки, поэтому все значения будут поступать из разных строк группы, если вы не пройдете некрасивую и неэффективную гимнастику. Это можно исправить только с помощью оконных функций, а неGROUP BY
.