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...
Какая должна быть правильная конфигурация запроса?
Ответы
Ответ 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')