Need help to Convert SQL to LINQ - sql

i need help, i need to convert the following query from SQL to LINQ.
and use it in my mvc view
select b.ID from LibraryTable a
left join User b on a.UserNumber=b.UserNumber

From msdn: Left Outer Joins
var query = from t in LibraryTable
join u in User on t.UserNumber equals u.UserNumber into tu
from d in tu.DefaultIfEmpty()
select new { Id = u == null ? 0 : u.ID };
However, you say you want a left join, but only select something from the right table. This example will just return 0 for anything in LibraryTable that does not have a User record. You may want to consider also selecting something from the left table. To do that, add a new property in the anonymous type in the select.

Related

MS Access, how to replace a saved query by the full query in a subquery

I have 3 tables:
1 - tblMembers_Info
2 - a junction table
3 - tblCourses
I need to query the members who haven't done a specific course.
After trying to do it manually I gave MS Access "Query Wizard" a try. I ended up with :
A saved query as Query1:
// That one query who did the course
SELECT tblMembers_Info.*, tblCourses.CourseName
FROM tblMembers_Info
INNER JOIN
(tblCourses INNER JOIN tblMembers_Courses
ON tblCourses.IDCourses = tblMembers_Courses.IDCourses)
ON tblMembers_Info.Members_ID = tblMembers_Courses.Members_ID
WHERE (tblCourses.CourseName) In ('NameOftheCourse');
2nd query using the saved Query1:
SELECT tblMembers_Info.Members_ID, tblMembers_Info.FirstName, tblMembers_Info.LastName
FROM tblMembers_Info
LEFT JOIN [Query1]
ON tblMembers_Info.[Members_ID] = Query1.[Members_ID]
WHERE (((Query1.Members_ID) Is Null));
How can I replace the Query1 in the second query with the full query instead of using a QueryDef (the saved query "Query1")?
Also, there's a better way for sure to write that query, I would really appreciate any help.
You can simply replace LEFT JOIN [Query1] with LEFT JOIN (...) AS [Query1] where ... should be the SQL of the first query, without the ending ;.
But I think in your specific case the use of NOT IN might give a better performance to get the same results:
SELECT tblMembers_Info.Members_ID, tblMembers_Info.FirstName, tblMembers_Info.LastName
FROM tblMembers_Info
WHERE tblMembers_Info.[Members_ID] NOT IN (
SELECT tblMembers_Info.[Members_ID]
FROM ((tblMembers_Info
INNER JOIN tblMembers_Courses
ON tblMembers_Info.Members_ID = tblMembers_Courses.Members_ID)
INNER JOIN tblCourses
ON tblCourses.IDCourses = tblMembers_Courses.IDCourses)
WHERE tblCourses.CourseName = 'NameOftheCourse'
);

Writing this SQL in LINQ? (outer apply)

My apologies for my recent SQL/Linq questions, but i need to know what this working SQL query would look like in LINQ?
select *
from CarePlan c
outer apply (select top 1 * from Referral r
where
r.CarePlanId = c.CarePlanId order by r.ReferralDate desc) x
left outer join Specialist s on s.SpecialistId = x.SpecialistId
left outer join [User] u on u.UserId = s.UserId
This basically retrieves a list of Careplans with the newest Referral (if it exists), then joins the Specialist and User table based on any found Referrals
Thanks
Kind advice: target on what you want to express in the environment of your class model and LINQ, in stead of trying to reproduce SQL. If you do something like
context.CarePlans
.Select(cp => new { Plan = cp, FirstReferral = cp.Referrals.FirstOrDefault() }
(provided that it matches your context and ignoring ordering and other joins for clarity)
It would basically do what you want, but it may very well translate to an inline subquery, rather than an OUTER APPLY. To the same effect. And the execution plan probably won't differ very much.

Sql syntax to always get one

SELECT dbo.Calls.Description, dbo.TicketRead.IsRead, dbo.TicketRead.UserID
FROM dbo.Calls
LEFT OUTER JOIN dbo.TicketRead ON dbo.Calls.CallID = dbo.TicketRead.TicketID
WHERE dbo.TicketRead.UserID = 1 or is null
I want to get a list of all calls, but also a value indicating if the user have read the call. so I made when a user open's the ticket a new record is added in a special table.
now if no user have read it then it's ok, but if just one user have read this ticket, then the other users don't have this call in the list..
I'm using msSql and .net entity framework.
Are you sure you want to limit the TicketRead table to just UserID # 1?
SELECT c.Description, r.IsRead, r.UserID
FROM dbo.Calls c
LEFT JOIN dbo.TicketRead r
ON c.CallID = r.TicketID
AND r.UserID = 1
This is done joining on multiple conditions... You'll get all of the Calls, but only the IsRead flag from TicketRead when UserID #1 has read it.
I'm not convinced this is actually what you're looking for, and I will be available to update this later if not.
Also please consider using table aliases in the future, I think you'll like it.
you are wanting to do the following:
SELECT dbo.Calls.Description, dbo.TicketRead.IsRead, dbo.TicketRead.UserID
FROM dbo.Calls
LEFT OUTER JOIN dbo.TicketRead ON dbo.Calls.CallID = dbo.TicketRead.TicketID
WHERE
dbo.TicketRead.UserID = 1
or dbo.TicketRead.CallID IS NULL
basically, we are saying here, if there a userid, it has to be 1. otherwise, the records primary key is null (because of the join). Fosco's answer is also right, and much smaller :)

NHibernate HQL logic problem

I'm trying to write an NHibernate HQL query that makes use of parenthesis in the where clause. However, the HQL parser seems to be ignoring my parenthesis, thus changing the meaning of my statement. Can anyone shed any light on the matter?
The following HQL query:
from WebUser u left join fetch u.WebUserProfile left join fetch
u.CommunicationPreferences where (u.CommunicationPreferences.Email = 0 and
u.SyncDate is not null) or u.DateDeleted is not null
translates to:
from WebUser webuser0_
left outer join WebUserProfile webuserpro1_
on webuser0_.UserId = webuserpro1_.WebUserId
left outer join WebUserCommunicationPreferences communicat2_
on webuser0_.UserId = communicat2_.UserId
where communicat2_.Email = 0
and (webuser0_.SyncDate is not null)
or webuser0_.DateDeleted is not null
Thanks
Jon
I know this is a late answer but I had to add my two cents.
In SQL the and operator takes precendence over the or operator.
So
(u.CommunicationPreferences.Email = 0
and u.SyncDate is not null) or
u.DateDeleted is not null
is the same as
communicat2_.Email = 0 and
(webuser0_.SyncDate is not null) or
webuser0_.DateDeleted is not null
The left join that you specify in the from clause, must be respected in all criterias in the where clause. You must take care of the special null case in all parts of the query, this is the way SQL (and HQL) works.
Reference : http://en.wikipedia.org/wiki/Null_(SQL)
when you write u.CommunicationPreferences.Email = 0, the CommunicationPreferences must be not null, or the database row will not be selected.
I suggest trying the following (adapt it to your own case) :
from WebUser u
left join fetch u.WebUserProfile w
left join fetch u.CommunicationPreferences c
where ( (c.Email = 0 or c is null)
and u.SyncDate is not null)
or u.DateDeleted is not null
Extract from the HQL Best-practices on our projects :
give aliases to all tables reached
for each nullable alias (w and c in this case), any constraint (c.Email = 0) must be or-ed with the null case (or c is null)
Added: To explain more :
The second LEFT join means that you want to select a WebUser even if there is no CommunicationPreferences that match. This is incompatible with a selection like u.CommunicationPreferences.Email, that excludes any match if u.CommunicationPreferences is null (read well, I don't refer to the Email column).
Such an incompatibility may cause strange translations, where you don't understand why the SQL was created that way ... Fix the HQL and try again :-) The parenthesis may become correct.

LEFT JOINing on additional criteria in MS Access

I have the following T-SQL query (a simple test case) running fine in MS SQL but cannot get the equivalent query in MS Access (JET-SQL). The problem is the additional criteria in the LEFT JOIN. How can I do this in MS Access?
T-SQL:
SELECT * FROM A
LEFT OUTER JOIN B ON A.ID = B.A_ID
AND B.F_ID = 3
JET-SQL (what I have so far but crashes Access!):
SELECT * FROM dbo_A
LEFT JOIN dbo_B ON (dbo_A.ID = dbo_B.A_ID AND dbo_B.F_ID = 3)
You need to use a subselect to apply the condition:
SELECT *
FROM dbo_A LEFT JOIN
[SELECT dbo_B.* FROM dbo_B WHERE dbo_B.F_ID = 3]. AS dbo_B
ON dbo_A.ID = dbo_B.A_ID;
If you're running Access with "SQL 92" compatibility mode turned on, you can do the more standard:
SELECT *
FROM dbo_A LEFT JOIN
(SELECT dbo_B.* FROM dbo_B WHERE dbo_B.F_ID = 3) AS dbo_B
ON dbo_A.ID = dbo_B.A_ID;
Do you need this to be editable in Access? If not, just use a passthrough query with the native T-SQL. If so, I would likely create a server-side view for this, and I'd especially want to move it server-side if the literal value is something you would parameterize (i.e., the F_ID=3 is really F_ID=N where N is a value chosen at runtime).
BTW, I write these subselect derived table SQL statements every single day while working in Access. It's not that big a deal.
Do you get an error message when it crashes or does it just lock up? Judging by the dbo_B name I'm going to guess that these are linked tables in Access. I believe that when you do a join like that Access doesn't tell SQL server that it needs the result of the join, it says, "Give me all of the rows of both tables" then it tries to join them itself. If the tables are very large this can cause the application to lock up.
You're probably better off creating a view on SQL Server for what you need.
I think ms access expect to both tables name in each section of Joins ON clause. As a trick this work for me:
SELECT * FROM A
LEFT OUTER JOIN B ON A.ID = B.A_ID
AND B.F_ID = IIF(True, 3, A.ID)
A.ID or any other else field from table A
That last condition technically isn't a join but a comparison to a literal value. Put it in a WHERE clause:
SELECT *
FROM a LEFT OUTER JOIN b ON a.ID = b.a_id
WHERE b.f_id = 3;