Hibernate criteria query for join with condition - sql

I have the following SQL query:
SELECT
tos.ID
FROM
TESTCYCLE_OPCO_SETTING tos
JOIN OPCO o
ON o.ID = tos.OPCO_ID
JOIN TESTCYCLE tc
ON tc.ID = tos.TESTCYCLE_ID
LEFT OUTER JOIN BUILD b
ON b.ID = tc.BUILD_ID
LEFT OUTER JOIN BUILD_OPCO_SETTING bos
ON bos.BUILD_ID = b.ID
AND bos.OPCO_ID = o.ID
What is needed is that the OPCO_ID form the TESTCYCLE_OPCO_SETTING is used to fetch the corresponding BUILD_OPCO_SETTING. I have done this with the "AND" condition in the last JOIN.
I now want to create a Hibernate Critera query out of this and created the following aliases for the joins:
criteria.createAlias("opco", "opco");
criteria.createAlias("testcycle", "testcycle");
criteria.createAlias("testcycle.build", "build", CriteriaSpecification.LEFT_JOIN);
criteria.createAlias("build.buildOpcoSettings", "buildOpcoSetting", CriteriaSpecification.LEFT_JOIN, Restrictions.eqProperty("buildOpcoSetting.opco.id", "opco.id"));
However the 4th alias throws an SQL error and I think I'm using this incorrectly for what I want to achieve. If I replace the property "opco.id" with a specific numeric value it works but this doesn't help me of course.
Any ideas?

Found the solution myself. Using the "opco" alias within the "buildOpcoSetting" alias lead to a wrong order of joins in the resulting SQL and an extra "opco" join. Replaced it with the opco reference from the "testcycleOpcoSetting" which works fine.
criteria.createAlias("build.buildOpcoSettings", "buildOpcoSetting", CriteriaSpecification.LEFT_JOIN,Restrictions.eqProperty("buildOpcoSetting.opco.id", "testcycleOpcoSetting.opco.id"));

Related

where clause conditions in SQL

Below is a join based on where clause:
SELECT a.* FROM TEST_TABLE1 a,TEST_TABLE2 b,TEST_TABLE3 c
WHERE a.COL11 = b.COL11
AND b.COL12 = c.COL12
AND a.COL3 = c.COL13;
I have been learning SQL from online resources and trying to convert it with joins
Two issues:
The original query is confusing. The outer joins (with the (+) suffix) are made irrelevant by the last where condition. Because of that condition, the query should only return records where there is an actual matching c record. So the original query is the same as if there were no such (+) suffixes.
Your query joins TEST_TABLE3 twice, while the first query only joins it once, and there are two conditions that determine how it is joined there. You should not split those conditions over two separate joins.
BTW, it is surprising that the SQL Fiddle site does not show an error, as it makes no sense to use the same alias twice. See for example how MySQL returns the error with the same query on dbfiddle (on all available versions of MySQL):
Not unique table/alias: 'C'
So to get the same result using the standard join notation, all joins should be inner joins:
SELECT *
FROM TEST_TABLE1 A
INNER JOIN TEST_TABLE2 B
ON A.COL11 = B.COL11
INNER JOIN TEST_TABLE3 C
ON A.COL11 = B.COL11
AND B.COL12 = C.COL12;
#tricot correctly pointed out that it's strange to have 2 aliases with the same name and not getting an error. Also, to answer your question :
In the first query, we are firstly performing cross join between all the 3 tables by specifying all the table names. After that, we are filtering the rows using the condition specified in the WHERE clause on output that we got after performing cross join.
In second query, you need to join test_table3 only once. Since now you have all the required aliases A,B,C as in the first query so you can specify 2 conditions after the last join as below:
SELECT A.* FROM TEST_TABLE1 A
LEFT JOIN TEST_TABLE2 B
ON A.COL11 = B.COL11
left join TEST_TABLE3 C
on B.COL12 =C.COL12 AND A.COL3 = C.COL13;

Issues while creating a view using SQL Server Management Studio 2017

Create a view vw_contacttypedetails for
a. ContactTypeId, Name from person.contacttype
b. BusinessEntityId, PersonId from person.businessentitycontact
c. Join both the tables, resulting in the final display of 4 columns (2 from each table as mentioned)
d. THEN, run a query to see the data in vw_contacttypedetails
I attempted but got an invalid object name. Below is my query:
create view vwcontacttypedetails
as
select ContactTypeID,Name,BusinessEntityID,PersonID
from tblContacttype
join tblbusinessentitycontact
on Contacttype.ContactTypeID = businessentitycontact.ContactTypeID
It seems your join statement is wrong...
create view vwcontacttypedetails
as
select c.ContactTypeID,b.Name,b.BusinessEntityID,b.PersonID
from tblContacttype c
join tblbusinessentitycontact b
on c.ContactTypeID = b.ContactTypeID
For how the syntax of joins works, have a look here:
https://www.w3schools.com/sql/sql_join.asp
And from the official Microsoft documentation:
https://learn.microsoft.com/en-us/sql/relational-databases/performance/joins?view=sql-server-2017
Specifying the join conditions in the FROM clause helps separate them from any other search conditions that may be specified in a WHERE clause, and is the recommended method for specifying joins. A simplified ISO FROM clause join syntax is:
FROM first_table join_type second_table [ON (join_condition)]
join_type specifies what kind of join is performed: an inner, outer, or cross join. join_condition defines the predicate to be evaluated for each pair of joined rows. The following is an example of a FROM clause join specification:
FROM Purchasing.ProductVendor JOIN Purchasing.Vendor
ON (ProductVendor.BusinessEntityID = Vendor.BusinessEntityID)
The following is a simple SELECT statement using this join:
SELECT ProductID, Purchasing.Vendor.BusinessEntityID, Name
FROM Purchasing.ProductVendor JOIN Purchasing.Vendor
ON (Purchasing.ProductVendor.BusinessEntityID = Purchasing.Vendor.BusinessEntityID)
WHERE StandardPrice > $10
AND Name LIKE N'F%'
GO
And for your next question have a look here:
https://stackoverflow.com/help/how-to-ask

RedShift SQL subquery with Inner join

I am using AWS Redshift SQL. I want to inner join a sub-query which has group by and inner join inside of it. When I do an outside join; I am getting an error that column does not exist.
Query:
SELECT si.package_weight
FROM "packageproduct" ub "clearpathpin" cp ON ub.cpipr_number = cp.pin_number
INNER JOIN "clearpathpin" cp ON ub.cpipr_number = cp.pin_number
INNER JOIN (
SELECT sf."AWB", SUM(up."weight") AS package_weight
FROM "productweight" up ON up."product_id" = sf."item_id"
GROUP BY sf."AWB"
HAVING sf."AWB" IS NOT NULL
) AS si ON si.item_id = ub.order_item_id
LIMIT 100;
Result:
ERROR: column si.item_id does not exist
It's simply because column si.item_id does not exist
Include item_id in the select statement for the table productweight
and it should work.
There are many things wrong with this query.
For your subquery, you have an ON statement, but it is not joining:
FROM "productweight" up ON up."product_id" = sf."item_id"
When you join the results of this subquery, you are referencing a field that does not exist within the subquery:
SELECT sf."AWB", SUM(up."weight") AS package_weight
...
) AS si ON si.item_id = ub.order_item_id
You should imagine the subquery as creating a new, separate, briefly-existing table. The outer query than joins that temporary table to the rest of the query. So anything not explicitly resulted in the subquery will not be available to the outer query.
I would recommend when developing you write and run the subquery on its own first. Only after it returns the results you expect (no errors, appropriate columns, etc) then you can copy/paste it in as a subquery and start developing the main query.

Join expression not supported SQL

SELECT
Trs.itemID, Trs.imtName, Trs.sumQty, Sum(whiQty)
FROM
((SELECT
trsitemID AS itemID, trsimtName AS imtName,
Sum(trsQty) As sumQty
FROM
tblTransactionSub AS T
WHERE
trstraID = 1231
AND trsActive = True
GROUP BY
trsitemID, trsimtName) AS Trs
INNER JOIN
tblWarehouseItem AS WHI ON Trs.itemID = WHI.whiitemID)
RIGHT JOIN
WHI ON Trs.trswhiID = WHI.whiID
WHERE
whiActive = True
AND whiCansel = False
AND whiwrhID = 19
GROUP BY
Trs.itemID,Trs.imtName, Trs.sumQty
HAVING
SUM(whiQty) < Trs.sumQty
If you please help me me out since I am new to SQL commands I can not easily find my mistake.
Thanks in advance
The error that occurred when I added the Right Join is:
Join expression not supported
In MS Access, you have to use parenthesises with multiple joins:
select ...
from
((table1
... join table2 on ...)
... join table3 on ...)
... join tableN
/edit/
As OP question changes its syntax often, then my answer seems out of place :) Initially there were no parens there.
About RIGHT JOIN: You need to use table name (or entire subselect) after JOIN keyword, not skip it or use some other alias. Your query part
RIGHT JOIN
WHI ON Trs.trswhiID = WHI.whiID
currently uses alias WHI, which is wrong in two ways: 1) it is not table name 2) it is already used. You need something like this:
RIGHT JOIN
tblWarehouseItem AS WHI2 ON Trs.trswhiID = WHI2.whiID
It could be possible that MS Access restricts your kind of JOINs usage (like INNER join should not come after LEFT join); I have currently no possibility to check precise rules.
Your problem is that you have no table name after the RIGHT JOIN:
RIGHT JOIN
ON Trs.trswhiID = WHI.whiID
Should be:
RIGHT JOIN YOURTABLENAMEHERE as alias
ON Trs.trswhiID = WHI.whiID
However, you have already defined Trs and Whi, so I have no idea what table you want there, or why. Perhaps you just want to change the INNER JOIN to a LEFT JOIN or RIGHT JOIN.

multiple sql joins not producing desired results

I'm new to sql and trying to tweak someone else's huge stored procedure to get a subset of the results. The code below is maybe 10% of the whole procedure. I added the lp.posting_date, last left join, and the where clause. Trying to get records where the posting date is between the start date and the end date. Am I doing this right? Apparently not because the results are unaffected by the change. UPDATE: I CHANGED THE LAST JOIN. The results are correct if there's only one area allocation term. If there is more than one area allocation term, the results are duplicated for each term.
SELECT Distinct
l.lease_id ,
l.property_id as property_id,
l.lease_number as LeaseNumber,
l.name as LeaseName,
lty.name as LeaseType,
lst.name as LeaseStatus,
l.possession_date as PossessionDate,
l.rent as RentCommencementDate,
l.store_open_date as StoreOpenDate,
msr.description as MeasureUnit,
l.comments as Comments ,
lat.start_date as atStartDate,
lat.end_date as atEndDate,
lat.rentable_area as Rentable,
lat.usable_area as Usable,
laat.start_date as aatStartDate,
laat.end_date as aatEndDate,
MK.Path as OrgPath,
CAST(laa.percentage as numeric(9,2)) as Percentage,
laa.rentable_area as aaRentable,
laa.usable_area as aaUsable,
laa.headcounts as Headcount,
laa.area_allocation_term_id,
lat.area_term_id,
laa.area_allocation_id,
lp.posting_date
INTO #LEASES FROM la_tbl_lease l
INNER JOIN #LEASEID on l.lease_id=#LEASEID.lease_id
INNER JOIN la_tbl_lease_term lt on lt.lease_id=l.lease_id and lt.IsDeleted=0
LEFT JOIN la_tlu_lease_type lty on lty.lease_type_id=l.lease_type_id and lty.IsDeleted=0
LEFT JOIN la_tlu_lease_status lst on lst.status_id= l.status_id
LEFT JOIN la_tbl_area_group lag on lag.lease_id=l.lease_id
LEFT JOIN fnd_tlu_unit_measure msr on msr.unit_measure_key=lag.unit_measure_key
LEFT JOIN la_tbl_area_term lat on lat.lease_id=l.lease_id and lat.isDeleted=0
LEFT JOIN la_tbl_area_allocat_term laat on laat.area_term_id=lat.area_term_id and laat.isDeleted=0
LEFT JOIN dbo.la_tbl_area_allocation laa on laa.area_allocation_term_id=laat.area_allocation_term_id and laa.isDeleted=0
LEFT JOIN vw_FND_TLU_Menu_Key MK on menu_type_id_key=2 and isActive=1 and id=laa.menu_id_key
INNER JOIN la_tbl_lease_projection lp on lp.lease_projection_id = #LEASEID.lease_projection_id
where lp.posting_date <= laat.end_date and lp.posting_date >= laat.start_date
As may have already been hinted at you should be careful when using the WHERE clause with an OUTER JOIN.
The idea of the OUTER JOIN is to optionally join that table and provide access to the columns.
The JOINS will generate your set and then the WHERE clause will run to restrict your set. If you are using a condition in the WHERE clause that says one of the columns in your outer joined table must exist / equal a value then by the nature of your query you are no longer doing a LEFT JOIN since you are only retrieving rows where that join occurs.
Shorten it and copy it out as a new query in ssms or whatever you are using for testing. Use an inner join unless you want to preserve the left side set even when there is no matching lp.lease_id. Try something like
if object_id('tempdb..#leases) is not null
drop table #leases;
select distinct
l.lease_id
,l.property_id as property_id
,lp.posting_date
into #leases
from la_tbl_lease as l
inner join la_tbl_lease_projection as lp on lp.lease_id = l.lease_id
where lp.posting_date <= laat.end_date and lp.posting_date >= laat.start_date
select * from #leases
drop table #leases
If this gets what you want then you can work from there and add the other left joins to the query (getting rid of the select * and 'drop table' if you copy it back into your proc). If it doesn't then look at your Boolean date logic or provide more detail for us. If you are new to sql and its procedural extensions, try using the object explorer to examine the properties of the columns you are querying, and try selecting the top 1000 * from the tables you are using to get a feel for what the data looks like when building queries. -Mike
You can try the BETWEEN operator as well
Where lp.posting_date BETWEEN laat.start_date AND laat.end_date
Reasoning: You can have issues wheres there is no matching values in a table. In that instance on a left join the table will populate with null. Using the 'BETWEEN' operator insures that all returns have a value that is between the range and no nulls can slip in.
As it turns out, the problem was easier to solve and it was in a different place in the stored procedure. All I had to do was add one line to one of the cursors to include area term allocations by date.