I have a SQL that counts rows per date truncate (months, days, hours). Think a history graph. Query works fine if executed in pgAdmin but fails in Java using EclipseLink.
pgAdmin query:
SELECT date_trunc( 'hour', delivered_at ),
COUNT(date_trunc( 'hour', delivered_at )) AS num
FROM messages
WHERE channel_type='EMAIL'
AND created_at>='2016-02-28 16:01:08.882'
AND created_at<='2016-02-29 16:01:08.882'
GROUP BY date_trunc( 'hour', delivered_at );
JPQL Named query
SELECT FUNCTION('date_trunc', 'hour', m.deliveredAt ),
COUNT(FUNCTION('date_trunc', 'hour', m.deliveredAt )) AS num
FROM Message m
WHERE m.channelType = :channelType
AND m.createdAt >= :fromDate
AND m.createdAt <= :toDate
GROUP BY FUNCTION('date_trunc', 'hour', m.deliveredAt )
EclipseLink debugging log:
SELECT date_trunc(?, delivered_at), COUNT(date_trunc(?, delivered_at)) FROM messages
WHERE (((channel_type = ?) AND (created_at >= ?)) AND (created_at <= ?)) GROUP BY date_trunc(?, delivered_at)
bind => [hour, hour, EMAIL, 2015-12-27 00:00:00.0, 2015-12-27 00:00:00.0, hour]
Error:
ERROR: column "messages.delivered_at" must appear in the GROUP BY
clause or be used in an aggregate function Position: 23
PostgreSQL log:
2016-03-01 13:22:08 CET ERROR: column "messages.delivered_at" must
appear in the GROUP BY clause or be used in an aggregate function at
character 23 2016-03-01 13:22:08 CET STATEMENT: SELECT date_trunc($1,
delivered_at), COUNT(delivered_at) FROM messages WHERE (((channel_type
= $2) AND (created_at >= $3)) AND (created_at <= $4)) GROUP BY date_trunc($5, delivered_at) 2016-03-01 13:22:08 CET LOG: execute
S_2: SELECT 1
If I replace the binded variables from EclipseLink logged query and execute it in pgAdmin the query works. What is going on here?
Edit: Just to clarify, it also works using em.createNativeQuery.
PostgreSQL can have trouble with resolving parameter binding, which in this case manifests as native SQL with parameters inline work, while JPA generated SQL which defaults to bound parameters fails.
One solution is to turn off parameter binding by passing "eclipselink.jdbc.bind-parameters" with a value of "false" as either a query hint for the specific query, or as a persistence unit property to turn off parameter binding by default for all queries.
On postgresql, you can use the following syntax
GROUP BY 1
That means you will group you agregate using the first selected attribute in the SELECT clause. That might be helpful there
Related
I have the following JPA query that truncates dates to a full hour and counts them:
SELECT a.alertconfiguration.id.id,
date_trunc('hour', a.date) AS fromDate,
count(*) AS count
FROM alert a
GROUP BY a.alertconfiguration.id.id,
a.alertlevel,
date_trunc('hour', a.date)
I'm running this in a Spring Boot application using Hibernate. It works fine. But I don't want to duplicate the function call to date_trunc.
I have tried referring to fromDate in the GROUP BY clause but then I get an exception org.postgresql.util.PSQLException: ERROR: column "fromdate" does not exist
http://hibernate.atlassian.net/browse/HHH-9301 also states it is not possible to refer to aliases in the group by clause.
How could I rewrite my query without the duplicate function call?
Can you give a try using 2 instead of date_trunc('hour', a.date) in group by clause, as fromdate is 2nd column
Hibernate does not work with alias in group by or any aggregate functions. And as you will see in your sql query generated, the alias is different than that you have assigned.
while executing the following query using Hibernate
select to_char(vdadCloseDate,'yyyymm'), count(*) from RmDashboardAccountDataBe where 1=1 and vdadRmId in('MK13','MK11') GROUP BY TO_CHAR(vdadCloseDate,'YYYYMM')
I'm getting the following exception,
java.sql.SQLSyntaxErrorException: ORA-00979: not a GROUP BY expression
Is there any way to handle this issue?
This is "pure" Oracle SQL (i.e. not HQL) which looks exactly like your query (I had to use different table and column names, though):
SQL> select to_char(hire_date, 'yyyymm'), count(*)
2 from employees
3 where department_id in (10, 20)
4 group by to_char(hire_date, 'yyyymm');
TO_CHA COUNT(*)
------ ----------
200309 1
200508 1
200402 1
SQL>
So - yes, it works OK.
This is a link to HQL Group by clause which also suggests that such a query is perfectly valid (have a look so that I wouldn't have to copy/paste its contents over here).
That's why I asked whether you're sure that this is the query that returned ORA-00979 error. As you responded that it is, huh, I wouldn't know what to say ...
(Edit 1: not Date but wc_Event.date)
I created a query (with subquery) that executes perfectly but I have trouble converting it either to a JPA query or a stored procedure.
This is my query:
SELECT * FROM wc_Event WHERE (wc_Event.date > CURRENT_DATE())
AND wc_Event.evt_id IN
(
SELECT event_users.evt_id FROM event_users
WHERE event_users.usr_id = 1
)
ORDER BY wc_Event.date
I have tried this for stored procedure:
CREATE PROCEDURE getFutureRegistredEvents
(
my_user_id int
)
BEGIN
SELECT * FROM wc_Event WHERE (wc_Event.date > CURRENT_DATE())
AND wc_Event.evt_id IN
(
SELECT event_users.evt_id FROM event_users
WHERE event_users.usr_id = my_user_id
)
ORDER BY wc_Event.date
END
It tells me to use the right syntax at line 13 (= END) but even if I add a semicolon to it my query wont work.
I also tried creating the same effect with JPA queries but with no effect.
What am I doing wrong?
Thanks in advance
Bert
I have been working with Oracle and Postgre and recently switched to MS SQL 2012.
I use hibernate in my application and wherever I have used the Order by Criteria:
(criteria.addOrder(Order.asc("applicationId")));
It causes an error saying:
aggregate functions dont work.
Once I comment that line out my program works and data can be retrieved.
I'm using Hibernate 3.
Is there any way to order it through hibernate without this error?
edit..
This is one error I get,
Column "SKY.tcrent.RENTNO" is invalid in the ORDER BY clause because
it is not contained in either an aggregate function or the GROUP BY
clause.
Edit 2..
MY query
Query tcSchaduleQ = getSession().createQuery("SELECT SUM(tcs.dueAmount) FROM TrialCalculationSchedule tcs WHERE tcs.facilityId=:facilityId AND tcs.rentalNumber>:rentalNumber AND tcs.dueDate>:dueDate AND dueTypeId IN(:dueTypeId) ORDER BY tcs.rentalNumber ").setInteger("rentalNumber", facility.getPeriod() - noOfprePayments).setInteger("facilityId",facility.getFacilityId()).setDate("dueDate", date).setParameterList("dueTypeId", plist);
Number tcsAmt = (Number) tcSchaduleQ.uniqueResult();
and this is what hibernate generates in HQL
SELECT
SUM(tcs.dueAmount)
FROM
TrialCalculationSchedule tcs
WHERE
tcs.facilityId=:facilityId
AND tcs.rentalNumber>:rentalNumber
AND tcs.dueDate>:dueDate
AND dueTypeId IN(
:dueTypeId
)
ORDER BY
tcs.rentalNumber
and this is the SQL
select
SUM(trialcalcu0_.DUEAMT) as col_0_0_
from
SKYBANKSLFHP.tcrent trialcalcu0_
where
trialcalcu0_.FACID=?
and trialcalcu0_.RENTNO>?
and trialcalcu0_.DUEDATE>?
and (
trialcalcu0_.DUETYPEID in (
? , ?
)
)
order by
trialcalcu0_.RENTNO
Look Like you mix aggregate and non-aggregate expressions .If you are using any aggregate function like AVG() in Select query with some other non-aggregate then you must use Group By ..
Try something like this
createQuery("SELECT SUM(tcs.dueAmount) As DueAmount ...
If you are using Criteria then it should be like this
Criteria crit = sess.createCriteria(Insurance.class);
ProjectionList proList = Projections.projectionList();
proList.add(Projections.sum("investementAmount"));
crit.setProjection(proList);
List sumResult = crit.list();
Consider the below query:
insert into dbo.SubscriptionDetails (taxonomyid)
values(select objectid from SubscriptionObjects where objectname=?)
This query works fine in my local environment and but gives issues while executed the production environment.
Does the sub-select query needs any properties to be set on the SQL-Server level?
I use Java - JDBC for SQL transactions.
See stack trace below:
2013.03.28 15:42:11 CDT ERROR Error while inserting records into SubscriptionDetails table..
java.sql.BatchUpdateException: Subqueries are not allowed in this context. Only scalar expressions are allowed.
I'm surprised your version works in any environment! Try to omit values:
insert into dbo.SubscriptionDetails
(taxonomyid)
select objectid
from SubscriptionObjects
where objectname=?
For more than one subquery, you can:
insert into dbo.SubscriptionDetails
(taxonomyid, contenttypeid)
select (select objectid from SubscriptionObjects where objectname=?)
, (select objectid from SubscriptionObjects where objectname=?)
Alternatively, use parenthesis to force scalar context with values:
insert into dbo.SubscriptionDetails
(taxonomyid, contenttypeid)
values ((select objectid from SubscriptionObjects where objectname=?),
(select objectid from SubscriptionObjects where objectname=?))