Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why no "SELECT foo.* ... GROUP BY foo.id" in Postgres?

Tags:

sql

postgresql

I have a query like this:

select foo.*, count(bar.id)
from foo inner join bar on foo.id = bar.foo_id
group by foo.id

This worked great with SQLite and MySQL. Postgres however, complains about me not including all columns of foo in the group by clause. Why is this? Isn't it enough that foo.id is unique?

like image 408
Sijmen Mulder Avatar asked Jul 16 '09 07:07

Sijmen Mulder


People also ask

What happens if I GROUP BY a column that is not in the SELECT statement Why does this happen?

No, you can GROUP BY a column that was not included in the SELECT statement. For example, this query does not list the price column in the SELECT , but it does group the data by that column.

Why do we need to use the same columns that are selected in SELECT list in the GROUP BY clause?

If you are grouping on something you cannot see the individual values of non-grouped columns because there may be more than one value within each group.

Can we include all the columns in GROUP BY clause?

The GROUP BY clause must contain all the columns except the one which is used inside the group function.

Which columns can be used in GROUP BY?

The GROUP BY statement groups rows that have the same values into summary rows, like "find the number of customers in each country". The GROUP BY statement is often used with aggregate functions ( COUNT() , MAX() , MIN() , SUM() , AVG() ) to group the result-set by one or more columns.


2 Answers

Just in case other people stumble over this question:

Starting with PostgreSQL 9.1 it's sufficient to list the columns of the primary key in the group by clause (so the example from the question would work now).

like image 57
a_horse_with_no_name Avatar answered Oct 14 '22 09:10

a_horse_with_no_name


Some databases are more relaxed about this, for good and bad. The query is unspecific, so the result is equally unspecific. If the database allows the query, it will return one record from each group and it won't care which one. Other databases are more specific, and require you to specify which value you want from the group. They won't let you write a query that has an unspecific result.

The only values that you can select without an aggregate is the ones in the group by clause:

select foo.id, count(bar.id)
from foo inner join bar on foo.id = bar.foo_id
group by foo.id

You can use aggregates to get other values:

select foo.id, min(foo.price), count(bar.id)
from foo inner join bar on foo.id = bar.foo_id
group by foo.id

If you want all the values from the foo table, you can either put them all in the group by clause (if that gives the correct result):

select foo.id, foo.price, foo.name, foo.address, count(bar.id)
from foo inner join bar on foo.id = bar.foo_id
group by foo.id, foo.price, foo.name, foo.address

Or, you can join the table with a subquery:

select foo.id, foo.price, foo.name, foo.address, sub.bar_count
from foo
inner join (
   select foo.id, bar_count = count(bar.id)
   from foo inner join bar on foo.id = bar.foo_id
   group by foo.id
) sub on sub.id = foo.id
like image 35
Guffa Avatar answered Oct 14 '22 09:10

Guffa