PostgreSQL – GROUP BY или используется в агрегатной функции

Я нашел здесь несколько тем, но я все еще не могу найти нужную настройку для моего запроса.

Это запрос, который хорошо работает на localhost:

@cars = Car.find_by_sql('SELECT cars.*, COUNT(cars.id) AS counter FROM cars LEFT JOIN users ON cars.id=users.car_id GROUP BY cars.id ORDER BY counter DESC') 

Но на Heroku дается ошибка выше – предложение GROUP BY или используется в агрегатной функции .

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

 @cars = Car.find_by_sql('SELECT cars.id, cars.name, cars.created_at, cars.updated_at, COUNT(cars.id) AS counter FROM cars LEFT JOIN users ON cars.id=users.car_id GROUP BY (cars.id, cars.name, cars.created_at, cars.updated_at) ORDER BY counter DESC') 

Но это не работает на localhost, а также не на Heroku …

Какая должна быть правильная конфигурация запроса?

Я думаю, вы пытаетесь агрегировать и группировать в одном столбце. Это зависит от того, какие данные вы хотите. Эфир:

 SELECT cars.name, cars.created_at, cars.updated_at, COUNT(cars.id) AS counter FROM cars LEFT JOIN users ON cars.id=users.car_id GROUP BY cars.name, cars.created_at, cars.updated_at ORDER BY counter DESC 

Или вы хотите все рассчитать? Тогда вот так:

 SELECT cars.id, cars.name, cars.created_at, cars.updated_at, COUNT(*) AS counter FROM cars LEFT JOIN users ON cars.id=users.car_id GROUP BY cars.id, cars.name, cars.created_at, cars.updated_at ORDER BY counter DESC 

Запрос, такой как этот (получение всех или большинства строк), выполняется быстрее, если вы GROUP перед вами JOIN . Как это:

 SELECT id, name, created_at, updated_at, u.ct FROM cars c LEFT JOIN ( SELECT car_id, count(*) AS ct FROM users GROUP BY 1 ) u ON u.car_id = c.id ORDER BY u.ct DESC; 

Таким образом, вам нужно гораздо меньше операций объединения. И ряды табличных cars не нужно сначала умножать, присоединяясь ко многим пользователям каждый, а затем снова группировать, чтобы быть уникальными.
Необходимо сгруппировать только правую таблицу, что упрощает логику.

Вы можете использовать MAX() трюк в колонке автомобилей.

 @cars = Car.find_by_sql(' SELECT cars.id, MAX(cars.name) as name, MAX(cars.created_at) AS created_at, MAX(cars.updated_at) as updated_at, COUNT(cars.id) AS counter FROM cars LEFT JOIN users ON cars.id=users.car_id GROUP BY cars.id ORDER BY counter DESC')