【问题标题】:PostgreSQL - GROUP BY clause or be used in an aggregate functionPostgreSQL - GROUP BY 子句或用于聚合函数
【发布时间】:2012-04-27 01:10:57
【问题描述】:

我在 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')

但这不适用于本地主机,也不适用于 Heroku...

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

【问题讨论】:

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


    【解决方案1】:

    如果您在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 的行不必首先通过加入多个用户来相乘,然后再分组为唯一。
    只需对正确的表进行分组,这也使逻辑更简单。

    【讨论】:

      【解决方案2】:

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

      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
      

      【讨论】:

        【解决方案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')
        

        【讨论】:

        • 知道使用 max 这样会导致性能问题吗?
        猜你喜欢
        • 2013-07-31
        • 2013-08-31
        • 2012-12-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-08-06
        相关资源
        最近更新 更多