PostgreSQL - GROUP BY子句或用于聚合函数

时间:2012-04-15 11:36:27

标签: sql ruby-on-rails-3 postgresql heroku

我在SO上找到了一些主题,但我仍无法找到正确的查询设置。

这是查询,在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 ...

查询的正确配置应该是什么?

3 个答案:

答案 0 :(得分:31)

如果您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的行不必首先通过连接到每个用户,然后再分组为唯一。 只有正确的表必须进行分组,这也使逻辑更简单。

答案 1 :(得分:28)

我认为您正在尝试在同一列上聚合和分组。这取决于您想要的数据。以太这样做:

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 :(得分:7)

您可以在汽车列上使用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')