Converting MySQL select to PostgreSQL

前端 未结 3 1153
無奈伤痛
無奈伤痛 2020-12-06 16:49

I have this query which works correctly in MySQL. More background on it here.

SELECT c.*, SUM(ABS(v.vote)) AS score
FROM categories c,items i, votes v
    W         


        
相关标签:
3条回答
  • 2020-12-06 17:13

    You have to list column names in SELECT which you are grouping in:

    SELECT c.id, c.name, SUM(ABS(v.vote)) AS score
    FROM categories c,items i, votes v
      WHERE c.id = i.category_id
      AND i.id = v.voteable_id
      AND v.created_at > '#{1.week.ago}'
    GROUP BY c.id, c.name
    ORDER BY score DESC LIMIT 8;
    

    "It is not permissible to include column names in a SELECT clause that are not referenced in the GROUP BY clause."

    0 讨论(0)
  • 2020-12-06 17:18

    If you change your statement to this it should work:

    SELECT c.id, SUM(ABS(v.vote)) AS score
    FROM categories c,items i, votes v
      WHERE c.id = i.category_id
      AND i.id = v.voteable_id
      AND v.created_at > '#{1.week.ago}'
    GROUP BY c.id
    ORDER BY score DESC LIMIT 8;
    

    I'm not sure what MySQL gives as a result, but to give you a very small example of why this does not work in PostgreSQL, take a look at the following categories table:

    id | name
    ---|-----
     1 | ABC
     1 | DEF
    

    You group by id, so each row in the result should contain just one id. If you select name also, without grouping by it, what should be shown in the result for name?

    It can be either ABC or DEF but the database engine can not really decide that for you (although MySQL apparently does).

    0 讨论(0)
  • 2020-12-06 17:24

    I just had that issue but going from MySQL to SQL Server. I thought the fact that it is allowed it was strange!

    Yes, in most databases, when you have a GROUP BY clause you can only select aggregates of columns or columns that appear in the GROUP BY clause. This is because it has no way of knowing if the other columns you're selecting are truly unique or not.

    Just put the columns you want in the GROUP BY if they are indeed unique. This was a "feature" of MySQL that was questionable.

    You can read about MySQL's behavior and how it is different here.

    Example:

    SELECT c.*, SUM(ABS(v.vote)) AS score
    FROM categories c,items i, votes v
        WHERE c.id = i.category_id
        AND i.id = v.voteable_id
        AND v.created_at > '#{1.week.ago}'
    GROUP BY c.id, c.name, c.whatever_else
    ORDER BY score DESC LIMIT 8;
    
    0 讨论(0)
提交回复
热议问题