I've written a JPQL statement that unions multiple select statements, each of which selects a different string constant. A simplified version of the query would look something like this:
SELECT DISTINCT 'A' AS widget_type
FROM WidgetA widgetA
WHERE widgetA.creationTimestamp > :cutoff
UNION SELECT DISTINCT 'B' AS widget_type
FROM WidgetB widgetB
WHERE widgetB.creationTimestamp > :cutoff
The query doesn't cause any errors but I'm not getting the result I expect. I see that the generated SQL doesn't have any unions - it only queries the table from the first select:
select distinct 'A' as col_0_0_
from widget_a widget0_
where widget0_.creation_timestamp>?
Is there an obvious reason why JPA would disregard everything after the first select statement? If it makes any difference, I am using Hibernate 4.1.9 as the JPA implementation, with a MySQL database.
JPQL has no such concept as UNION. So consequently any "query" that has it is not JPQL and so ought to be rejected as invalid JPQL (which DataNucleus JPA certainly would do)
Related
I need to implement select from a nested query, for the sake of simplicity let it be:
select * from (select * from city) c
How can this be done using CriteriaQuery and Subquery?
You can't because (select * from city) is not an entity and CritieriaAPI queries on entities not on tables.
The only way would be to create a view for (select * from city) and map that view to an entity.
First, your syntax is not JPA compliant as mentioned previously, secondly, you must know that subqueries in JPQL are allowed only in WHERE and HAVING clauses. The same applies to Criteria queries. If you need the more powerful SQL subquery features then with JPA you have to use JPA provisions for native queries, or otherwise, use another type of JDBC library.
I have following method defined:
#Query("SELECT AVG(total) FROM (SELECT COUNT(t.name) total FROM DataTable t GROUP BY DATE(actiontime)) result")
Long countAvg();
However it causes this error:
Caused by: org.hibernate.hql.internal.ast.QuerySyntaxException: unexpected token: ( near line 1, column 24 [SELECT AVG(total) FROM (SELECT COUNT(t.name) total FROM backend.DataTable t GROUP BY DATE(actiontime)) result]
But following SQL works fine:
SELECT AVG(total) FROM (SELECT COUNT(NAME) total FROM DATA_TABLE GROUP BY DATE(actiontime)) result
If i understand correctly, JPQL has problems with subquery. How should i create this kind of query then?
I don't think jpql supports subselect with from clause. As per jpa docs
Subqueries are restricted to the WHERE and HAVING clauses in this release. Support for subqueries in the FROM clause will be considered in a later release of the specification.
You can use nativeQuery = true in the #Query annotation and run it as native query instead or rewrite the query if possible.
When I execute this query in SQL Server which calls to IBM,
Select * from openquery(ibm,'
Select COST_AMT,'Query1' as Query
from table
where clause
with ur;
')
union
Select * from openquery(ibm,'
Select COST_AMT,'Query2' as Query
from table
different where clause
with ur;
')
I get different results in the union query than when I execute them separately and bring the results in together. I have tried the union query inside the openquery so I believe this is an IBM thing. The results appear to be a distinct selection of COST_AMT sorted by lowest to highest.
ie:
1,Query1
2,Query1
3,Query1
1,Query2
2,Query2
3,Query2
but the data is actually like this:
1,Query1
1,Query1
1,Query1
2,Query1
2,Query1
3,Query1
1,Query2
1,Query2
1,Query2
2,Query2
2,Query2
3,Query1
Am I missing something about the ibm union query? I realize I could sum and get the answer, (which is what I plan no doing) but I want to know more about why this is happening.
This has nothing to do with "ibm" or "db2" -- the SQL UNION operator removes duplicates. To retain duplicates use UNION ALL.
Is there a way to do an ordering in JPQL query like:
SELECT v
FROM Vehicle v
WHERE ...
ORDER BY v.lastUserUpdate DESC NULLS LAST, v.id DESC;
The NULLS LAST breaks the query. Is there a correct way to do this?
I don't know a JPQL function to allow this as I believe it is database specific. JPA 2.0 has a 'SQL' key word that you can use to have "nulls last" passed through. Something like
"ORDER BY v.lastUserUpdate DESC SQL('NULLS LAST'), ..."
See
http://java-persistence-performance.blogspot.ca/2012/05/jpql-vs-sql-have-both-with-eclipselink.html for more details on what is available in JPA and eclipselink. TopLink uses EclipsLink for JPA, so you will have to verify the version you are using and use native TopLink API if it doesn't support it and you can't upgrade.
I wrote the following query for MySQL:
SELECT subquery.t1_column1,
subquery.t2_id,
MAX(subquery.val)
FROM (
SELECT t1.column1 as t1_column1,
t1.id_t2 AS t2_id,
count(1) AS val
FROM table1 t1
INNER JOIN table2 t2
ON t2.id = t1.id_t2
GROUP BY t1.id_t2
) subquery
GROUP BY t1_column1
And I'd like to translate it into JPA (JPQL or criteria query).
I don't know how to make this max(count) thing, and JPA doesn't seem to like the SELECT FROM SELECT...
If anyone has an idea other than native queries (I'll do it for now), it would be great.
I haven't checked tha JPA specification, but given that the Hibernate documentation says
Note that HQL subqueries can occur only in the select or where
clauses.
I very much doubt that your query can be transformed in a valid JPQL query.
You'll have to keep using this native SQL query.
JPA 2.0 JPQL does not support sub-selects in the from clause. You may want to try to rewrite your query, or use a native SQL query.
EclipseLink 2.4 will support sub-selects in the FROM clause,
see,
http://wiki.eclipse.org/EclipseLink/UserGuide/JPA/Basic_JPA_Development/Querying/JPQL#Sub-selects_in_FROM_clause