For each order without invoice - java

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;

Related

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.

HQL nested subqueries

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
)

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();

How to flatten the results of a Hibernate query

Say I executed a theoretical HQL query like FROM Customer. And in Customer is a getOrders() getter returning a ManyToOne collection of Order objects. This executes a SQL statement selecting from Customer with a left join to Order.
Through the object model, I can programmaticly iterate over Customers and then iterate over Orders.
However, I want to convert the hierarchical object model to a flat tabular result of the left join so that the results would look much like that of this SQL query:
SELECT *
FROM Customer
LEFT JOIN Order on Customer.customerId = Order.customerId
Sample result:
Customer.customerId ... Order.orderId Order.customerId ...
1 200 1
2 201 2
2 202 2
3 NULL NULL
Is there an easy way to do this with Hibernate?
Depends what you want at the "scalar" level which you control through using an explicitl select clause.
select c, o
from Customer c left join c.orders o
returns you List of (Customer, Order) tuples. Or:
select c.id, c.name, o.id, ...
from Customer c left join c.orders o
which returns you a scalar projection of the atomic pieces.
In both cases you get back a List. You can use "dynamic instantiation" in both cases (though really its more useful in the second case imho):
select new CustomerOrderSummary( c.id, c.name, o.id, ... )
from Customer c left join c.orders o
where CustomerOrderSummary is just a plain class with matching constructor.
Possible you can do this via expressing of result set. http://docs.jboss.org/hibernate/orm/4.0/hem/en-US/html/query_native.html
From the example:
#SqlResultSetMapping(name="GetNightAndArea", entities={
#EntityResult(name="org.hibernate.test.annotations.query.Night", fields = {
#FieldResult(name="id", column="nid"),
#FieldResult(name="duration", column="night_duration"),
#FieldResult(name="date", column="night_date"),
#FieldResult(name="area", column="area_id")
}),
#EntityResult(name="org.hibernate.test.annotations.query.Area", fields = {
#FieldResult(name="id", column="aid"),
#FieldResult(name="name", column="name")
})
})
I think you can try retrieving results in Object[] e.g. below:
EntityManager entityManager = EntityManager.getEntityManager();
Query query= entityManager.createQuery("select cust, ord from Customer cust left outer join cust.orders ord where cust.customerId = :customerId");
tradeQuery.setParameter("customerId", aCustomerId);
List<Object[]> resultList = (List<Object[]>)query.getResultList();
The retrieved resultsList will be list of Object array containing Customer and Order objects in flat.
if(!resultList.isEmpty()){
Iterator<Object[]> iter = resultList.iterator();
while(iter.hasNext()){
Object[] resultObj = (Object[])iter.next();
Customer customer= (Customer )resultObj[0];
Order order = (Order)resultObj[1];
}
}
Hope this helps!

Categories

Resources