HQL nested subqueries - java

I have such domain: Country has cities, city has offices, offices has services. I need to find all countries with offices which provide specified service id. My current version is:
SELECT c FROM Country c
WHERE EXISTS(
SELECT ct FROM c.cities ct
WHERE EXISTS(
SELECT o FROM ct.offices o
WHERE EXISTS(
SELECT s.id FROM o.services s
WHERE s.id = :id
)
)
)
So, I'm new to HQL. What is best way to this? Is my version Ok? I was thinking about SELECT DISTINCT with LEFT JOIN too.

I don't think there is anything wrong with your query, but this might be more readable.
SELECT c FROM Country
WHERE EXISTS (
SELECT s.id FROM
c.cities ct
JOIN ct.offices o
JOIN o.services s
WHERE s.id = :id
)

Related

hql request with different tables

I want to write a complex hql query with relationships from 3 tables. It is necessary to make a selection of the selected columns so that they are located by ID
#Query("SELECT p.regId, p.method, p.tax, p.fee, p.netAmount, r.countSec, p.status " +
"FROM P p INNER JOIN R r INNER JOIN D d on p.regId = r.id AND p.regId = d.id")
List<P> findAllByRegId(String regId);
My compiler cannot execute the request, I don't understand what the problem is! Help, please
org.postgresql.util.PSQLException: ERROR: syntax error at or near "join"
The format for multiple joins is
SELECT columns ...
FROM table1 AS t1
INNER JOIN
table2 AS t2
ON t1.id = t2.id
INNER JOIN
table3 AS t3
ON t3.id = t1.id
Your join is totally wrong. You have to add ON keyword and map primary key and foreign key in first inner join.
Here is your join, which is wrong
SELECT columns FROM A a
INNER JOIN B b
INNER JOIN C c ON a.ColName = b.ColName AND a.ColName = c.ColName
Here is the correct syntex for multiple join
SELECT columns FROM A a
INNER JOIN B b ON a.ColName = b.ColName
INNER JOIN C c ON a.ColName = c.ColName
Here down is modified query
#Query("SELECT p.regId, p.method, p.tax, p.fee, p.netAmount, r.countSec, p.status " +
"FROM P p INNER JOIN R r ON p.regId = r.id INNER JOIN D d ON p.regId = d.id")

How to write "JPQL" query with "IN" between SELECTs?

I wrote this JPQL query and expect a result as List<Question>:
#Query("SELECT q FROM Question q WHERE q.id IN (SELECT qc.questions FROM QCard qc WHERE qc.id IN (SELECT ct.qCards FROM CTest ct WHERE ct.id=:id))")
These are my classes:
class CTest {
id, List<QCard>
}
class QCard{
id, List<Question>
}
class Question{
id
}
I expected all questions as return for given CTest.id.
But I got a compiler-error with message:
SQLSyntaxErrorException
I tried use ":" before "select" words but it had not helped.
What is wrong?
Test your SQL query in an SQL-client (e.g. Squirrel, DbVisualizer, etc.).
Assuming your foreign keys are named:
question_id in table QCard
card_id in table CTest
you could have an SQL with subselects like:
SELECT q.id
FROM Question q
WHERE q.id IN (
SELECT qc.question_id
FROM QCard qc
WHERE qc.id IN (
SELECT ct.card_id
FROM CTest ct
WHERE ct.id = 1 -- example test id
)
)
Does it return the expected result or are there syntax errors?
Then subsequently replace your subselects by JOINs.
Question and Cards
SELECT q.id, c.id
FROM Question q
JOIN QCard c ON c.question_id = q.id
Cards and Tests
SELECT c.id, t.id
FROM QCard c
JOIN CTest t ON t.card_id = c.id
All together
SELECT q.id, c.id, t.id
FROM Question q
JOIN QCard c ON c.question_id = q.id
JOIN CTest t ON t.card_id = c.id
Note: add WHERE clauses like WHERE t.id = 1 if needed.
Experiment with the FROM/JOIN order as it makes sense.
Then translate the running SQL query to JPQL. For example:
#Query("SELECT q"
+ " FROM CTest test"
// a test has many cards (1:n)
+ " JOIN QCard card ON card.id = test.card_id" // associated cards
// a card has many questions (1:n)
+ " JOIN Question q ON q.id = card.question_id" // associated questions
+ " WHERE test.id = :id")
public List<Question> findQuestionsByTestId(String id);
List<Question> findByIdIn(List<Long> idList); //In repository
or
String qlString = "select i from Item i where i.name IN :names";
Query q = em.createQuery(qlString, Item.class);
List<String> names = Arrays.asList("foo", "bar");
q.setParameter("names", names);
List<Item> actual = q.getResultList();
I did those example in my past work, check it, tnx
In your existing query, in inner queries you are selecting entities and checking IN against Id, which will definitely won't work. As you can't complete entry with the Id.
As you haven't shared your complete entity structure, assuming that you have two way relationship declared correctly in entities, here I am placing a reference query which uses the join:
#Query("SELECT q FROM Question q JOIN q.qCard qc WHERE q.qCardId = qc.id AND qc.cTestId = :id")
Where qCardId is the foreign key reference of QCard entity in Question entity and cTestId is the foreign key reference of CTest entity in QCard entity.
You can use this for your reference to update your query with joins.

For each order without invoice

i solve this task with 2 native query but want to solve this with one native query maybe will you show me the way if possible.
it's my first query:
select o.id as id,o.date as date,o.customer_id_id as customerId
from orders o left outer join
invoice i
on o.id = i.order_id_id
where i.order_id_id is null
intersect
select o.id as id,o.date as date,o.customer_id_id as customerId
from detail d join
orders o
on o.id = d.order_id_id
it's my second query and i use from first query o.id it's mean ?1=o.id:
select sum(d.quantity*p.price)
from product p join
detail d
on p.id=d.product_id_id
where d.order_id_id=?1
it is grafic of project
enter image description here
text of task:For each order without invoice, list its ID, the date it was placed and the total price of the
products in its detail, taking into account the quantity of each ordered product and its unit
price. Orders without detail must not be included in the answers.
If I understand correctly, this is an aggregation query after joining three tables (orders, detail, product). You can use NOT EXISTS or LEFT JOIN/WHERE to filter out the orders with no invoices:
select o.id, o.date, o.customer_id_id as customer_id,
sum(d.quantity*p.price)
from orders o join
detail d
on o.id = d.order_id_id join
product p
on p.id = d.product_id_id
where not exists (select 1
from invoices i
where o.id = i.order_id_id
)
group by o.id, o.date, o.customer_id_id;

Left_Join on same tables in Hibernate Criteria API

I have a table and a class marked as #Entity with
#Table(name="Employee")
It has two fields, Id and Name
i want to do left join on same table like,
Select t2.name, count(*)
from Employee t1 left join Employee t2 on t1.Id = t2.Id
where t1.Name = 'asd'
group by t2.Name
I had a workaround, I converted that query into sub query
Select EmployeeID From Employee
Where ManagerID in (Select EmployeeID where performance >= 4 )
And used DetachedCriteria and i got it worked. But this will reduce my performance. SO i will try your method and see if i can get it worked
Ref
https://forum.hibernate.org/viewtopic.php?p=2389790

JPQL with subquery to select max count

I'm trying to write a jpql query to select the user with the most comments. If two users have the same number of comments I want to select both.
I tried this, something like this:
SELECT
c.user, COUNT(c.id) as commentCount
FROM
Comment c
WHERE
commentCount = (SELECT MAX(SIZE(user.comments)) FROM User user)
GROUP BY
c.user
and this:
SELECT
c.user
FROM
Comment c
GROUP BY
c.user
HAVING
COUNT(c) = (SELECT MAX(SIZE(user.comments)) FROM User user)
Neither approach works. What do I need to do here?
Here is a solution:
SELECT
u
FROM
User u
WHERE
u.comments.size = (SELECT MAX(u2.comments.size) FROM User u2)
This should work if you are using Oracle:
select u from User u where size(u.comments) = (
select max(count(c.id))
from User u2 inner join u2.comments c
group by u2.id
)
But MySQL and SQL Server do not support nested aggregate functions, max(count(c.id)) in this case. It is suggested to use a subquery, but with HQL you cannot have subqueries in a from clause. So I suggest you do this manually, i.e. load all users:
select u, size(u.comments)
from User u
and loop through the list.
For any others coming here and wanting to select a max(count()) in jpql and doesn't have an array, (like in the question the comments) take following jpql code into consideration:
select e.city
from Employees e
group by e.city
having count(e.id) >= All(select count(e) from Employees e group by e.city)
full example in a JPA Repository:
#Query(value = "select e.city from Employees e group by e.city " +
"having count(e.id) >= All(select count(e) from Employees e group by e.city)")
public List<Cities> findCityByMaxEmployeeCount();

Categories

Resources