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

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

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

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

@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...

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

4b9b3361

Ответ 1

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

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

Ответ 2

Такой запрос (получение всех или большинства строк) быстрее, если вы 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 не обязательно должны быть сначала умножены, присоединяясь ко многим пользователям каждый, а затем снова сгруппированные, чтобы быть уникальными.
Необходимо сгруппировать только правую таблицу, что упрощает логику.

Ответ 3

Вы можете использовать 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')