Doctrine, key offset, "JOIN bar b ON f.id = b.id - 1" - doctrine

The database I work with has an offset on one of the table's key. In plain SQL this would look like:
SELECT * FROM foo f LEFT JOIN bar b ON f.id = b.id - 1
I tried to use Expr\Join::ON with QueryBuilder, but that gives me an error saying that Expected end of string, got 'ON'. Example below.
I also tried Expr\Join::WITH with QueryBuilder, but that returns nothing for that join. In other words, $element->getBar() returns null. Example below.
I cannot modify the database structure or data. I have to work with it as it is.
Example of QueryBuilder usage:
return $this
->createQueryBuilder('f')
->select('f, b')
->leftJoin('f.bar', 'b', Expr\Join::ON, 'f.id = b.id - 1');
// ->leftJoin('f.bar', 'b', Expr\Join::WITH, 'f.id = b.id - 1');

Related

Syntax issues with pervasive SQL if statement used to determine left join on clause

Back Story: I am looking to do a left join based on if a condition is true with an if statement. However if it is false, I want to still join the said table in, but with the same columns or with a new set of columns. This query is being wrote for a Pervasive SQL DB.
This query is fairly large, without this particular issue it executes and returns the data sets as expected. Below is a snapshot of the issue I am currently running into..
SELECT A.ONUM, B.JN, C.SEQ, C.PN
From Z.OH
LEFT JOIN OL A ON Z.ONUM = A.ONUM
LEFT JOIN JH B ON A.ONUM = B.SNUM AND A.OLNUM = B.SLNUM AND B.CLSD <> 'Y'
LEFT JOIN JO C ON IF(A.LC <> 'ZY', B.JN = C.JN, LEFT(B.C_PO, 6) = C.JN OR B.JN = C.JN) AND C.OP_T NOT IN ('Z','C')
WHERE Z.OT <> 'T' AND C.PN NOT IN (SELECT X.PN FROM JH X WHERE B.JN = X.JN)
Again, very summarized version with lots of joins/filters/select statement removed.
I am running into issues on the join with the IF statement. Without the if statement, the query executes as expected.
The original join being: B.JN = C.JN AND C.OP_T NOT IN ('Z', 'C')
When executing the query in PCC it would give the following syntax error at the following point: "B.JN << ??? >> = C.JN"
I tried switching over to an OR statement as shown below, but the run time of the query made it an impossible choice.
LEFT JOIN JO C ON
(B.JN = C.JN) OR (A.LC = 'ZY' AND LEFT(B.C_PO, 6) = C.JN)
AND C.OP_T NOT IN ('Z','C')
Checking the documentation, it looks like the query on the if statement is following the correct syntax...
Most simple solution would be to avoid the IF in the WHERE-clause, and do:
SELECT A.ONUM, B.JN, C.SEQ, C.PN
From Z.OH
LEFT JOIN OL A ON Z.ONUM = A.ONUM
LEFT JOIN JH B ON A.ONUM = B.SNUM AND A.OLNUM = B.SLNUM AND B.CLSD <> 'Y'
LEFT JOIN JO C ON (A.LC <> 'ZY' AND B.JN = C.JN) OR (A.LC = 'ZY' AND (LEFT(B.C_PO, 6) = C.JN OR B.JN = C.JN))
AND C.OP_T NOT IN ('Z','C')
WHERE Z.OT <> 'T' AND C.PN NOT IN (SELECT X.PN FROM JH X WHERE B.JN = X.JN)

JPQL query with having oracle db

I am using jpql jpa eclipselink Following query wont work :
SELECT c FROM TableA c WHERE c.forumId = :forumId AND c.isDefault = true HAVING MAX (c.validFrom)
The error im getting "The expression is not a valid conditional expression"
The HAVING clause only works with a GROUP BY expression.
The HAVING clause allows for the results of a GROUP BY to be filtered.
Your question is:
i want o get max validFrom how can i make expression ot of this
But you can make a query without GROUP BY and HAVING to do what you want:
select c from TableA c WHERE c.validFrom = (
SELECT MAX(c2.validFrom)
FROM TableA c2
WHERE c2.Id = c.Id AND c.forumId = :forumId AND c.isDefault = true
)
If you would like to use GROUP BY and HAVING, you can do:
SELECT c FROM TableA c WHERE c.validFROM = (
SELECT MAX(validFROM)
FROM TableA
WHERE forumId = :forumId AND isDefault = true
GROUP BY validFROM
HAVING validFROM=c.validFROM
)

sql select records that don't have relation in a third table

I have three tables
CLAIMS_TB
CLAIMS_RISK_TB
VEHICLE_TB
And then I need this result below:
Who can help me or share with me the query to be used?
N.B: If the code is 700 it means that it is a vehicle and it must fill the column called "ai_vehicle_use" otherwise it must leave it blank because "VEHICLE_TB" table contains only vehicles
This is what I tried:
select
klm.CM_PL_INDEX,
klm.cm_no,
klmrisk.cr_risk_code,
CASE WHEN klm.CM_PR_CODE = '0700' THEN klmrisk.cr_risk_code ELSE '' END,
veh.ai_vehicle_use
from CLAIMS_TB klm
JOIN CLAIMS_RISK_TB klmrisk
ON (klm.cm_index = klmrisk.cr_cm_index)
INNER JOIN VEHICLE_TB veh
on veh.ai_regn_no = klm.cm_no
where klm.cm_no='CL/01/044/00001/01/2018'
or klmrisk.cr_cm_index='86594'
order by klmrisk.cr_risk_code;
I believe this could fit your needs.
SELECT
*
FROM CLAIMS_TB AS c
LEFT JOIN CLAIMS_RISK_TB cl ON c.cm_index = cl.cr_cm_index
LEFT JOIN VEHICLE_TB v ON cl.cr_risk_code = v.ai_risk_index
Finaly I find the solution, query below works:
select * from CLAIMS_TB c
JOIN CLAIMS_RISK_TB cr ON( C.CM_INDEX = cr.cr_cm_index)
LEFT OUTER JOIN VEHICLE_TB v ON (cr.cr_risk_code = v.ai_regn_no);

Where Clause on Joined Table with Into Keyword

I wish to join two tables while filtering one of the tables. That works fine like
var matching = from a in ctx.A
join b in ctx.B on a.BId equals b.Id
where idList.Contains(b.Id)
select a;
However, if I also make use of the into keyword to name the joined result
var matching = from a in ctx.A
join b in ctx.B on a.BId equals b.Id into c
where idList.Contains(b.Id)
select a;
I get a compiler error telling me
The name 'b' does not exist in the current context
However, I can reference a at that point, as well as 'c', without problems.
Why is that exactly, and how can I apply a where clause to b?
Why is that exactly
Because after a join into clause, the range variable introduced by that clause isn't in scope - whereas previous variables are. Don't forget that you're joining into c, so each value of b is effectively part of the group of values (c).
and how can I apply a where clause to b?
By doing it earlier:
var matching = from a in ctx.A
join b in ctx.B.Where(x => idList.Contains(x.Id))
on a.BId equals b.Id into c
where c.Any()
select a;
EDIT: This can be put into slightly more query-expression-oriented code as:
var matchingBs = from b in ctx.B
where idList.Contains(b.Id)
select b;
var matching = from a in ctx.A
join b in matchingBs
on a.BId equals b.Id into c
where c.Any()
select a;
(You could use a nested query expression, but I'm not keen on those in general.)
Or using Any on c:
var matching = from a in ctx.A
join b in ctx.B on a.BId equals b.Id into c
where c.Any(b => idList.Contains(b.Id))
select a;
Or even:
var matching = from a in ctx.A
where ctx.B.Any(b => idList.Contains(x.Id) &&
a.BId == b.Id)
select a;
Which can be rewritten as:
var matching = ctx.A.Where(a => ctx.B.Any(b => idList.Contains(x.Id) &&
a.BId == b.Id));
It's important to understand the difference in results between join and join into - the first creates a "pairwise" join; the second creates a group join, where the result for the extra range variable is a group of matches.

Oracle: column ambiguously defined

I know there are lots of questions like these, but my question is not how to get rid of this error but to know how this worked earlier in 9-th version of Oracle.
I've got an old sources written in Ruby and Oracle DB which recently was upgraded to version=11.
I cannot edit data in Oracle DB, only read. so there are two tables lets say: table A(id, name, type, customer) and table B(id,a_id,type,person)
so. there is a query in the source code:
select a.id,b.id from a join b on a.id = b.a_id where type = 'A'
so in Oracle 9 this worked perfectly but now i've got "column ambiguously defined" error.
What i'd like to know is:
where type = 'A'
is the same as
where a.type = 'A' AND b.type = 'A'
or
where a.type = 'A' OR b.type = 'A'
?
I think this was a bug with the ANSI style join. Use DBMS_XPLAN to find which table was being filtered in the old database.
Or better still, work out from the business logic what they query SHOULD have been.
No, and that's the problem: It could mean
where a.type = 'A'
or it could mean
where b.type = 'A'
with potentially different results; hence the error saying it is ambiguously defined.
I think you should test in Oracle 9 (where you say it works) and compare the output of the ambiguous query:
--- Base
select a.id,b.id from a join b on a.id = b.a_id where type = 'A'
with both the non-ambiguous ones:
--- QueryA
select a.id,b.id from a join b on a.id = b.a_id where a.type = 'A'
and:
--- QueryB
select a.id,b.id from a join b on a.id = b.a_id where b.type = 'A'
Something like this would do:
select a.id,b.id from a join b on a.id = b.a_id where type = 'A'
MINUS
select a.id,b.id from a join b on a.id = b.a_id where a.type = 'A'
(in short):
(Base)
MINUS
(QueryA)
and then:
(QueryA)
MINUS
(Base)
If both of the above MINUS queries return 0 rows, then BASE query is interpreted as QueryA.
Check similarly and compare Base with QueryB.
Another plausible reason for this error is that during (or about the same period with ) the migration, a type column was added in the 2nd table. Do you have old versions of the database tables' definitions to check that?
All - keep in mind there was a major change to the optimization engine for 11g. If you set your query optimizer level to 10.2.x on your 11g instance I bet the query would start working again.
That being said you should provide the alias for it so it's not ambiguous to the database server or the DBA / Developer coming behind you. :)

Resources