MultiPOCO queries firing error message - tsql

I have a query as
return Connection.db.Fetch<Issue, Condition , Result , Status>(
"SELECT * FROM Issue I, Condition C, Result R, Status S " +
"LEFT JOIN Issue ON Condition .ID = Issue.ConditionID" +
"LEFT JOIN Issue ON Result.ID = Issue.ResultID" +
"LEFT JOIN Issue ON Status.ID = Issue.StatusID " +
"WHERE Issue.ID= "+ issueId);
which is giving the error message:
The multi-part identifier "Condition.ID" could not be bound.
The objects "Issue" and "Issue" in the FROM clause have the same exposed names. Use correlation names to distinguish them.
What is worng with the above?

You're joining to Issue table several times, but never use aliases. This is especially a problem because you've added the same table to FROM part of your SELECT clause. Always use aliases in joins. It's the safest way.
So whenever you said Issue.ID query engine could not resolve to which one you're referring. Is it to the one in FROM part or the one in JOIN part.
Try out this code:
return Connection.db.Fetch<Issue, Condition , Result , Status>(
"SELECT * FROM Issue I, Condition C, Result R, Status S " +
"LEFT JOIN Issue i1 ON C.ID = i1.ConditionID" +
"LEFT JOIN Issue i2 ON R.ID = i2.ResultID" +
"LEFT JOIN Issue i3 ON S.ID = i3.StatusID " +
"WHERE I.ID = " + issueId);
And apart from that I strongly suggest you use parameters instead of string concatenation:
return Connection.db.Fetch<Issue, Condition , Result , Status>(
"SELECT * FROM Issue I, Condition C, Result R, Status S " +
"LEFT JOIN Issue i1 ON C.ID = i1.ConditionID" +
"LEFT JOIN Issue i2 ON R.ID = i2.ResultID" +
"LEFT JOIN Issue i3 ON S.ID = i3.StatusID " +
"WHERE I.ID = #0", issueId); // see the change in this line
After some thought this is actually invalid SQL query
The problem that you're having is not PetaPoco related at all. You've actually written an invalid SQL query. If you'd run this same statement in SSMS you'd get the same error and that's because your query is interpreted as:
SELECT * FROM Issue I, Condition C, Result R,
(Status S
LEFT JOIN Issue i1
ON C.ID = i1.ConditionID
LEFT JOIN Issue i2
ON R.ID = i2.ResultID
LEFT JOIN Issue i3
ON S.ID = i3.StatusID
)
WHERE I.ID = x;
And that's the main reason why the first two joins fail. The last one is the only one that works, because it sees both tables. You probably thought that your select makes a result of those tables and then joins as in:
SELECT * FROM (Issue I, Condition C, Result R, Status S)
LEFT JOIN ...
But that is not the case.
Depending on what kind of results you want (you may end up with a large result set the way that you're doing it) you will have to rewrite your query to a different form and possibly omit the multi table list in your FROM part.

Related

Join a table with a specific condition

I have three tables:
"user" who has one or more rows associated with him in the "contractYear" table, which consists of rows in a "contract_month" table.
I want to get the result set of users who do not have contract months for the current contract year (i.e. contract Year.endDate < current date)
I made the following query:
#Query("select distinct u "
+ " from User u "
+ " left join u.contractYears cy"
+ " on cy.endDate < now()"
+ " left join cy.contractMonths cm"
+ " where cm is null")
But it doesn't work...
I assume the condition "on cy.endDate < now()" is not correct.
Maybe someone can help me make the correct query?
In HQL if you need additional filter in join clause you can add using WITH keyword
select distinct u
from User u
left join u.contractYears cy
with cy.endDate < now()
left join cy.contractMonths cm
where cm is null
See 14.3. Associations and joins section

What's the difference between "NOT EXISTS" and "NOT IN"

For school I needed to get all players who never played a match for the team with number 1. So I thought I would look for all players who played a match for the team with number 1 in a subquery. This is my subquery:
select distinct s.spelersnr, naam
from spelers s inner join wedstrijden w on (s.spelersnr = w.spelersnr and teamnr = 1)
Now to extract the players who never played a match for team 1 I thought I could use the "NOT EXISTS" operator. My query then looked like this:
select spelersnr, naam
from spelers
where not exists (select distinct s.spelersnr, naam
from spelers s inner join wedstrijden w on (s.spelersnr = w.spelersnr and teamnr = 1))
order by naam, spelersnr
But this query didn't return the result I needed (in fact it didn't return anything). Then I tried this query:
select spelersnr, naam
from spelers
where (spelersnr, naam) not in (select distinct s.spelersnr, naam
from spelers s inner join wedstrijden w on (s.spelersnr = w.spelersnr and teamnr = 1))
order by naam, spelersnr
This query returned the result I needed, but now I don't really understand the difference between "NOT EXISTS" and "NOT IN".
You where close, the difference between the NOT EXISTS and NOT IN is how the SQL is executed, using NOT IN will be much slower (obviously this depends on the size of the data sets involved) because it compares each row to each of the items in the clause.
in contrast EXISTS or NOT EXISTS does a lookup for the single row based on a a contextual where clause.
All that's missing in you example is the WHERE clause in the EXISTS
select spelersnr, naam
from spelers as sp
where not exists (select 1
from spelers s inner join wedstrijden w on (s.spelersnr = w.spelersnr and teamnr = 1)
where sp.spelersnr = s.spelersnr and sp.naam = s.naam)
order by naam, spelersnr
Hope this helps :)

Sql to LINQ query LINQ Query convert

I have a SQL query I want to write in LINQ
Here is my Query
SELECT DISTINCT *
FROM [IHQDB].[dbo].[Table1] as t1
inner join Table2 as t2 on t2.Table2 =t1.ChangedItemID
inner join Table3 as t3 on t3.Table3 = t1.FromUserID
where (t1.FromUserID=1 And t2.ContentItemID= t1.ChangedItemID)
OR (t2.LastModifiedBy=1 or t2.CreatedBy=1 )
Hi now its working fine but My query little bit different on place of 1 I need my userID on base of their First Name and Last Name from M_User table.
How can I get UserId on Base of First Name + Last Name.
Here is my LINQ CODE For Retrieving User Name
linq4 = from q in context.T_ContentItems
join p in context.M_Users on q.CreatedBy equals p.UserID
where (advanceKeyword.Contains(p.EmployeeFirstName + " " + p.EmployeeLastName)) select q;
advancechk12 = linq4.ToList();
========================================================================
What I require is that wherever I have written the value "1" (e.g. t2.CreatedBy=1), I need to find the UserID. For simplicity, I am able to get the names of all the filtered users in the advancechk12. How do I retrieve the UserID's of the list of usernames returned in advancechk12
You have to replace below mentioned Linq query with your models name.I just used the same name of the T-Sql.
var t1List = (from t1 in db.Table1
join t2 in db.Table2 on t1.ChangedItemID equals t2.Id
join t3 in db.Table3 on t3.Id equals t1.FromUserID
where ((t1.FromUserID=1 && t2.ContentItemID= t1.ChangedItemID) || (t2.LastModifiedBy=1 or t2.CreatedBy=1))
select t1).Distinct().ToList();

JPA is changing my query and giving me completely wrong results

I'm using EntityManager ("em") and creating a query using the method "createQuery", but it changes my query, If I use the method "createNativeQuery" it works fine, but than I can't add a list to parameters.
String query = " SELECT t0.id FROM Movie t0, Tagged t1, Tag t2 "
+ " WHERE t2.id = t1.tagfk AND t1.moviefk = t0.id AND t2.name in :tagList "
+ " GROUP BY t0.id HAVING count(distinct t2.id) = :size "
+ " ORDER BY count(t1) DESC, t0.popularity DESC";
Query q = em.createQuery(query, Integer.class);
q.setParameter("tagList", tagList);
q.setParameter("size", tagList.size());
q.setMaxResults(20);
result = (List<Integer>)q.getResultList();
The problem here is, when I print the query
System.out.println(q);
I got
SELECT t0.ID AS a1 FROM MOVIE t0, TAG t2, TAGGED t1 WHERE (((t2.ID = t1.TAGFK) AND
(t1.MOVIEFK = t0.ID)) AND (t2.NAME IN ?)) GROUP BY t0.ID
HAVING (COUNT(DISTINCT(t0.ID)) = ?) ORDER BY COUNT(t1.ID) DESC, t0.POPULARITY DESC LIMIT ? OFFSET ?"))
If you look closer, the:
HAVING count(distinct t2.id) = :size
became
HAVING (COUNT(DISTINCT(t0.ID)) = ?)
And obvious I got wrong result, it is checking the wrong table.
Is it a bug or I'm doing something wrong? I can't find why it is happening. thanks.
I solved it doing the follow:
First:
Update from JPA 2.0.X to 2.1.X
Second:
In the HAVING clause I added the column used in the SELECT and GROUP BY with a statement that doesn't interfere with anything:
HAVING t0.id IS NOT NULL AND count(distinct t2.id) = :size
The solution above does not work on 2.0.X, it will result in:
HAVING (COUNT(DISTINCT(t0.ID)) = ?) AND (COUNT(DISTINCT(t0.ID)) = ?)
weird!!!
I'm using Eclipse Link, I forgot to mention that.
It just works, but still, I'm not happy with the HAVING parser on JPA, it needs improvement.

How to access a OnetoMany join table in JPQL?

I want to write a lttl complicated query in JPQL where i access a OneToMany Join table. I get QuerySyntaxException: Pan_PanRes is not mapped.
QUERY -
query = "SELECT p FROM Pan p WHERE p.id IN " +
"(SELECT p_id FROM Pan_PanRes p_prs WHERE prs_id IN " +
"(SELECT r.id FROM PRS r where r.pant = :pant))"+
" ORDER BY pr.clD"
i tried implementing this concept in MYSQL. It works fine. So i know i am not calling the join table in right way. How should it be called then?
I would like to add MYSQL statement which works fine -
mysql> select * from pan where id not in
(select pan_id from pan_panres where panres_id in
(select id from panres where pant_id = 3));
Thanks...
Solved it myself -
query = "SELECT p FROM Pan p WHERE p.id IN " +
"(SELECT p.id FROM p.panRes prs WHERE id IN " +
"(SELECT r.id FROM PanRes r where r.pant = :pant))"+
" ORDER BY pr.clD"
Where panRes is the oneToMany variable name i have used in Pan Class.