'PostgreSQL asking for 'group by' clause in where, when sending parameters
I have a simple query in PostgreSQL which is ok when I run it without any query parameters :
select date_trunc('week', action_time),count(*) from event
group by date_trunc('week', action_time);
But if I try to send the 'week' as a parameter like this (in Java):
PreparedStatement statement = connection.prepareStatement
("select date_trunc(?, action_time),count(*) from event"
+ " group by date_trunc(?, action_time)");
statement.setString(1,"week");
statement.setString(2,"week");
statement.execute();
it'll throw the following error:
ERROR: column "event.action_time" must appear in the GROUP BY clause or
be used in an aggregate function
is this normal behavior ?
Solution 1:[1]
When the query is prepared there's no guarantee that you will bind the same value ('week'
) for both placeholders. If you don't, the query would be illegal, and that's why postgres doesn't allow preparing it.
One way around this could be to change your query so you only bind 'week'
once, and use it from inside a subquery:
PreparedStatement statement = connection.prepareStatement
("select dt, count(*) from (select date_trunc(?, action_time) as dt "
+ "from event) s group by dt");
statement.setString(1,"week");
statement.execute();
Solution 2:[2]
I think this should work, but Postgres can be a bit finicky. For instance, the following does not work:
select date_trunc(val, now())
from (select 'week' as val) t
But this does:
select date_trunc(val, now())
from (select cast('week' as text) as val) t
You might check if this version works:
select date_trunc(datepart, action_time), count(*)
from event cross join
(select cast(? as text) as datepart) vars
group by date_trunc(datepart, action_time);
And then supply only one parameter.
Solution 3:[3]
Like Mureinik mentioned its because postgres cant prove the statement arguments are the same.
I was able to use a column alias to provide the argument once.
eg
select date_trunc(?, action_time), count(*) from event
group by date_trunc(?, action_time);
becomes
select date_trunc(?, action_time) as action_t, count(*) from event
group by action_t;
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Mureinik |
Solution 2 | Gordon Linoff |
Solution 3 | Stephen |