Add =value in a left join clause using execute query - java

Working with grails 3.3.8 and Mysql DB 5.5.x version.
I have done this query:
String query = $/
select new Map( i1.id as id,i1.name as name)
from CustomerComposition as c1
inner join c1.instrument as i1
left join i1.analisys as a1,
Instrument as i2
left join i2.analisys as a2,
Instrument as i3
left join i3.analisys as a3
where
i1.id=i2.id and i1.id=i3.id and
c1.portfolio.id=:ptfId and a1.phase.id=:p1Id and a2.phase.id=:p2Id and a3.phase.id=:p3Id
/$
List composition = CustomerComposition.executeQuery(query,
[ptfId: ptfId, p1Id: phase[0], p2Id: phase[1], p3Id: phase[2]])
The left join doesn't work. Then I realize that it doesn't work because I put a clause inside the WHERE. I double check with simple SQL statment and indeed it works once moved the conditional out the where. A simple snip taken just for clarification, before and it did not work:
SELECT
instrument1_.id
FROM
customer_ptf_composition customerpt0_
INNER JOIN instrument instrument1_ ON customerpt0_.instrument_id = instrument1_.id
LEFT JOIN analisys analisys4_ ON instrument1_.id = analisys4_.instrument_id
WHERE
customerpt0_.portfolio_id =1216
AND analisys4_.phase_id =111
and after and it works due to how left/right join works:
SELECT
instrument1_.id
FROM
customer_ptf_composition customerpt0_
INNER JOIN instrument instrument1_ ON customerpt0_.instrument_id = instrument1_.id
LEFT JOIN analisys analisys4_ ON instrument1_.id = analisys4_.instrument_id AND analisys4_.phase_id =111
WHERE
customerpt0_.portfolio_id =1216
Now my question is how can I put the "and field=value" next to the left join in GORM?

You can use the WITH clause to achive this:
left join i3.analisys a3 WITH a3.something = :someValue
See also: current Hibernate user guide: HQL explicit join

Related

LEFT JOIN freezes query execution

I have a pretty simple sql query:
SELECT o.description, oi.description, cu.name
FROM dbo.order o
LEFT JOIN dbo.orderitem oi o.orderItemId = oi.orderItemId
INNER JOIN dbo.customer cu on cu.customerId = o.customerId
WHERE cu.id = 12345
That query works, every time.
If I change the INNER JOIN to a LEFT JOIN...
LEFT JOIN dbo.customer cu on cu.customerId = o.customerId
then it always freezes when I call it with Java (via REST) and sometimes freezes if I am using my SQL Client. Sometimes it just works with the exact same search parameter and returns a few rows (<10) as expected.
Freezes means that it won't even start counting the execution time in my SQL client (SQuirreL) and that it will run into a timeout when I call it in Java.
But it will work again if I add a second WHERE clause like
SELECT o.description, oi.description, cu.name
FROM dbo.order o
LEFT JOIN dbo.orderitem oi o.orderItemId = oi.orderItemId
LEFT JOIN dbo.customer cu on cu.customerId = o.customerId
WHERE cu.id = 12345
AND o.someOtherId = 3456
or remove the cu.id completely.
Does anyone have any clue why that could happen?
I am not getting this line..
LEFT JOIN dbo.orderitem am oi o.orderItemId = oi.orderItemId
Dont you think it should be like:
LEFT JOIN dbo.orderitem oi on o.orderItemId = oi.orderItemId
Can you try?
This is because the left join on customer makes the where clause ineffective; the query would return all orders, with all orderitems, but only for orders of customer 12345, it would also return the customer name.
Maybe you want to do a right join instead, so you get the customer name even if he has no orders?

SQL Query builder utility

I have a Set of columns and Tables, in respective drop downs, I am working on a Code to generate a dynamic SQL based on the Table-Column selection
It's working in case of simple Select statements but in the case of Multiple Joins, I am trying to figure out a Syntax for handlin Right and Left Joins.
Please help..this is the Error for SQL Syntax
1)
(Select dbo.Employee.Dept_ID,dbo.Employee.Emp_ID,dbo.Employee.Emp_Name,dbo.Employee_DataVal.DeptNo,
dbo.Employee_DataVal.EmpName,dbo.Employee_DataVal.EmpNo,dbo.Employee_DataVal.Salary,dbo.Emp_Sal.Emp_ID,dbo.Emp_Sal.Salary
FROM Employee
INNER JOIN Employee_DataVal
ON Employee.Dept_ID = Employee_DataVal.DeptNo
OR Employee_DataVal.EmpName = Employee.Emp_Name)
LEFT JOIN Emp_Sal
ON Employee.Emp_ID = Emp_Sal.Emp_ID
Incorrect syntax near the keyword 'LEFT'.
2)Select dbo.Employee.Dept_ID,dbo.Employee.Emp_ID,
dbo.Employee.Emp_Name,dbo.Employee_DataVal.DeptNo,
dbo.Employee_DataVal.EmpName,dbo.Employee_DataVal.EmpNo
,dbo.Emp_Sal.Emp_ID,dbo.Emp_Sal.Salary
FROM Employee INNER JOIN Employee_DataVal
ON Employee.Emp_ID = Employee_DataVal.EmpNo
AND Employee.Dept_ID = Employee_DataVal.DeptNo
LEFT JOIN Employee
ON Employee_DataVal.EmpName = Employee.Emp_Name
The objects "Employee" and "Employee" in the FROM clause have the same exposed names. Use correlation names to distinguish them.
PS: Running this sql on SQL server
This is a common problem when working with complex dynamic SQL strings on a string basis - the correct handling of the SQL syntax in its string form is difficult, and it is easy to create SQL injection vulnerabilities as well.
SQL builder APIs like jOOQ and others are very well suited for this task. I'm not sure what exactly the problem was in your case, but let's just assume that the last LEFT JOIN is optional in your query. You could write a query like this:
List<Field<?>> c = new ArrayList<>(Arrays.asList(
EMPLOYEE.DEPT_ID,
EMPLOYEE.EMP_ID,
EMPLOYEE.EMP_NAME,
EMPLOYEE_DATAVAL.DEPTNO,
EMPLOYEE_DATAVAL.EMPNAME,
EMPLOYEE_DATAVAL.EMPNO,
EMPLOYEE_DATAVAL.SALARY
));
Table<?> t = EMPLOYEE
.join(EMPLOYEE_DATAVAL)
.on(EMPLOYEE.DEPT_ID.eq(EMPLOYEE_DATAVAL.DEPTNO)
.or(EMPLOYEE_DATAVAL.EMPNAME.eq(EMPLOYEE.EMP_NAME));
if (someCondition) {
t = t.leftJoin(EMP_SAL).on(EMPLOYEE.EMP_ID.eq(EMP_SAL.EMP_ID));
c.addAll(Arrays.asList(
EMP_SAL.EMP_ID,
EMP_SAL.SALARY
));
}
Result<?> result =
ctx.select(c)
.from(t)
.fetch();
Speaking directly to the syntax errors:
The parentheses in this statement are invalid. Removing them will solve the problem.
The table Employee is used twice in the FROM clause. You must alias the tables for this to work.
Select dbo.Employee.Dept_ID,dbo.Employee.Emp_ID,
dbo.Employee.Emp_Name,dbo.Employee_DataVal.DeptNo,
dbo.Employee_DataVal.EmpName,dbo.Employee_DataVal.EmpNo
,dbo.Emp_Sal.Emp_ID,dbo.Emp_Sal.Salary
FROM Employee e1 INNER JOIN Employee_DataVal
ON e1.Emp_ID = Employee_DataVal.EmpNo
AND e1.Dept_ID = Employee_DataVal.DeptNo
LEFT JOIN Employee e2
ON Employee_DataVal.EmpName = e2.Emp_Name
Speaking to your broader question, the concept of a generic SQL query generator is quite common and has had several implementation. You won't find full implementation guidance in a forum such as this.
Cheers!
You are using LEFT Join same as the Self join. which is actually creating the problem.
In first case error is coming because of the wrong ) in wrong place as pointed below; Which making the end of query and so LEFT JOIN throwing an error. the ) must be at end of the query.
FROM Employee
INNER JOIN Employee_DataVal
ON Employee.Dept_ID = Employee_DataVal.DeptNo
OR Employee_DataVal.EmpName = Employee.Emp_Name ) <--Here
LEFT JOIN Emp_Sal
In second case, you are trying to do a self join to the same table in that case as the error already suggested you, you need to use correlation names like
FROM Employee emp1 <-- Here used a table alias emp1
INNER JOIN Employee_DataVal ed
ON emp1.Emp_ID = ed.EmpNo
AND emp.Dept_ID = ed.DeptNo
LEFT JOIN Employee emp2 <-- Here used a different table alias emp2
ON ed.EmpName = emp2.Emp_Name
Moreover, the LEFT JOIN Employee won't make any sense here and which can simply be modified to below code
FROM Employee emp1
INNER JOIN Employee_DataVal ed
ON emp1.Emp_ID = ed.EmpNo
AND emp.Dept_ID = ed.DeptNo
AND emp.Emp_Name = ed.EmpName <-- here by adding another join condition

Hibernate left join does not return null rows when filtered using where condition

I have the below query in MySQL
SELECT Max(b.updated_at) as latest_date, r.resource,
COUNT(bill) as bills FROM Resource r
left join BillComp ba on (r.resource=ba.resource and comp=6)
This returns null values if t could not map a resource with the given company which is the requirement.
I need to convert to HQL and I am having issues in returning null raws as expected.
I have tried below two methods but none works
SELECT COUNT(bill), r.resource, MAX(b.updatedAt) FROM Resource r
left join r.billComp ba left join ba.bills b where ba.comp.comp = ?1
SELECT COUNT(bill), r.resource, MAX(b.updatedAt) FROM Resource r
left join r.billComp with ba.comp.comp = ?1 ba left join ba.bills b
Can someone show me how to get null values
I am using JPA Annotations

Simulating a database DELETE CASCADE

Above is how my database table structure looks like. B refers to A, C refers to A, D refers to B and so on. Now, I am running an offline job, that drops all constraints on these tables and deletes a few records by evaluating them in my java application. So for instance, delete from A WHERE id > 20, will be translated into a bunch of selects.
SELECT B.ID, A.ID FROM B,A WHERE B.FKEY = A.ID
SELECT C.ID, A.ID FROM C,A WHERE C.FKEY = A.ID
SELECT D.ID, A.ID FROM D,B,A WHERE B.FKEY = A.ID AND D.FKEY = B.ID
... so on..
.. finally.. SELECT H.ID, A.ID FROM A,B,D,F,H WHERE B.FKEY = A.ID AND D.FKEY = B.ID AND F.FKEY = D.ID AND H.FKEY = F.ID UNION SELECT H.ID, A.ID FROM A,C,E,G,H WHERE C.FKEY = A.ID AND E.FKEY = C.ID AND G.FKEY = E.ID AND H.FKEY = G.ID
Retrieving that data and verfifying for A.ID > 20 in code and then deleting what are not required is how my application performs delete (I know it might sound a little crazy, but this is how it is supposed to work).
Now the question I have here is this... How do I make this generic? My challenge is to identify tables like "H" that have multiple inheritance (or say that form cycles in the ER graph). I've tried looking into graph theory, but it is pretty confusing - way too much information for me to process.
In short, I would like to identify cycles in the ER graph and construct UNION queries for such tables.

How use hibernate criteria for a left outer join without direct link into the two tables

I'm trying to translate a SQL quest into Hibernate criteria.
My quest is working in SQL :
select * from objective
left outer join conditionstate
on objective.conditionid = conditionstate.conditionid
and conditionstate.personid = XXXX
where objective.toto_id = YYYYY
The objective is not directly mapped to the condition_state, but into a condition.
objective --> condition <-- condition_state
I've tested something like :
final DetachedCriteria criteriaObjective =
DetachedCriteria.forClass(Objective.class);
criteriaObjective.createAlias("conditionState", "conditionState", Criteria.LEFT_JOIN);
without success..
It's hard to suggest something without seeing your actual mappings. Going by your explanation and assuming that both condition and conditionState are mapped as many-to-one, you'd write something like:
final DetachedCriteria criteriaObjective =
DetachedCriteria.forClass(Objective.class);
criteriaObjective
.createCriteria("condition", Criteria.LEFT_JOIN)
.createCriteria("conditionState", Criteria.LEFT_JOIN)
.add(Restrictions.eq("personid", "XXXX") );
criteriaObjective.add(Restrictions.eqProperty("toto_id", "YYYY") );
Note that the above is NOT equivalent to the SQL query you've provided because "personid" condition will be generated as part of "WHERE" clause. As far as I know it's impossible to do a left join with condition using Criteria API - you may need to use HQL instead which provides with keyword for that exact purpose:
select o from objective as o
left join o.condition as c
left join c.conditionState as cs
with cs.person_id = 'XXXX'
and o.toto_id = 'YYYY'

Categories

Resources