Sql to LINQ query LINQ Query convert - entity-framework

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();

Related

JPA query returning a Tuple where one part is an Entity

I have two unrelated tables that I want to do an LEFT JOIN on, I only want 1 column from the LEFT table but the entire entity (which I intend to update if its present or create if not) from the right.
Simplified version of tables:
TABLE1
id, type, data
TABLE2
id, type, and, other, stuff
Current JPQL:
SELECT T1.type,
(SELECT T2
FROM TABLE2 T2
WHERE T2.id = T1.id
AND T2.type = T1.type)
FROM T1
WHERE T1.id = :ID
I am currently getting some sort of logical union error...
Can this been done or should I just use separate queries?
The exact exception is:
Caused by: java.lang.ClassCastException: org.apache.openjpa.jdbc.sql.LogicalUnion$UnionSelect incompatible with org.apache.openjpa.jdbc.sql.SelectImpl
The Java code I use follows:
Query q = this.em.createQuery(jql, Tuple.class);
q.setParameter("ID", id);
#SuppressWarnings("unchecked")
List<Tuple> result = q.getResultList();
The subquery is not essential to my solution - it's just the only form that was parseable - a regular SQL LEFT JOIN wasn't. In words what I am trying to do is for a given ID in TABLE1 find all rows in TABLE2 that have the same ID and type or null if there is no row. Later code will create rows in TABLE2 where there are none for the id and type. I'm expecting 2-3 types per ID in TABLE1 and about half the time for a matching row in TABLE2.

Lateral query syntax

I'm trying to get lateral to work in a Postgres 9.5.3 query.
select b_ci."IdOwner",
ci."MinimumPlaces",
ci."MaximumPlaces",
(select count(*) from "LNK_Stu_CI" lnk
where lnk."FK_CourseInstanceId" = b_ci."Id") as "EnrolledStudents",
from "Course" c
join "DBObjectBases" b_c on c."Id" = b_c."Id"
join "DBObjectBases" b_ci on b_ci."IdOwner" = b_c."Id"
join "CourseInstance" ci on ci."Id" = b_ci."Id",
lateral (select ci."MaximumPlaces" - "EnrolledStudents") x
I want the right-most column to be the result of "MaximumPlaces" - "EnrolledStudents" for that row but am struggling to get it to work. At the moment PG is complaining that "EnrolledStudents" does not exist - which is exactly the point of "lateral", isn't it?
select b_ci."IdOwner",
ci."MinimumPlaces",
ci."MaximumPlaces",
(select count(*) from "LNK_Stu_CI" lnk
where lnk."FK_CourseInstanceId" = b_ci."Id") as "EnrolledStudents",
lateral (select "MaximumPlaces" - "EnrolledStudents") as "x"
from "Course" c
join "DBObjectBases" b_c on c."Id" = b_c."Id"
join "DBObjectBases" b_ci on b_ci."IdOwner" = b_c."Id"
join "CourseInstance" ci on ci."Id" = b_ci."Id"
If I try inlining the lateral clause (shown above) in the select it gets upset too and gives me a syntax error - so where does it go?
Thanks,
Adam.
You are missing the point with LATERAL. It can access columns in tables in the FROM clause, but not aliases defined in SELECT clause.
If you want to access alias defined in SELECT clause, you need to add another query level, either using a subquery in FROM clause (AKA derived table) or using a CTE (Common Table Expression). As CTE in PostgreSQL acts as an optimization fence, I strongly recommend going with subquery in this case, like:
select
-- get all columns on the inner query
t.*,
-- get your new expression based on the ones defined in the inner query
t."MaximumPlaces" - t."EnrolledStudents" AS new_alias
from (
select b_ci."IdOwner",
ci."MinimumPlaces",
ci."MaximumPlaces",
(select count(*) from "LNK_Stu_CI" lnk
where lnk."FK_CourseInstanceId" = b_ci."Id") as "EnrolledStudents",
from "Course" c
join "DBObjectBases" b_c on c."Id" = b_c."Id"
join "DBObjectBases" b_ci on b_ci."IdOwner" = b_c."Id"
join "CourseInstance" ci on ci."Id" = b_ci."Id"
) t

Get Greatest date across multiple columns with entity framework

I have three entities: Group, Activity, and Comment. Each entity is represented in the db as a table. A Group has many Activities, and an Activity has many comments. Each entity has a CreatedDate field. I need to query for all groups + the CreatedDate of the most recent entity created on that Group's object graph.
I've constructed a sql query that gives me what I need, but I'm not sure how to do this in entity framework. Specifically this line: (SELECT MAX(X)
FROM (VALUES (g.CreatedDate), (a.CreatedDate), (c.CreatedDate)) Thanks in advance for your help. Here's the full query:
WITH GroupWithLastActivityDate AS (
SELECT DISTINCT
g.Id
,g.GroupName
,g.GroupDescription
,g.CreatedDate
,g.ApartmentComplexId
,(SELECT MAX(X)
FROM (VALUES (g.CreatedDate), (a.CreatedDate), (c.CreatedDate)) AS AllDates(X)) AS LastActivityDate
FROM Groups g
LEFT OUTER JOIN Activities a
on g.Id = a.GroupId
LEFT OUTER JOIN Comments c
on a.Id = c.ActivityId
WHERE g.IsActive = 1
)
SELECT
GroupId = g.Id
,g.GroupName
,g.GroupDescription
,g.ApartmentComplexId
,NumberOfActivities = COUNT(DISTINCT a.Id)
,g.CreatedDate
,LastActivityDate = Max(g.LastActivityDate)
FROM GroupWithLastActivityDate g
INNER JOIN Activities a
on g.Id = a.GroupId
WHERE a.IsActive = 1
GROUP BY g.Id
,g.GroupName
,g.GroupDescription
,g.CreatedDate
,g.ApartmentComplexId
I should add that for now I've constructed a view with this query (plus some other stuff) which I'm querying with a SqlQuery.

Linq to SQL self join where right part of join is filtered

I am trying to map a self join where the right table must be filtered, e.g. SQL such as this:
select t2.* from table t
left join table t2
on t2.parentID = t.ID and t2.active=1;
I can figure out the syntax if I wanted to filter the left table:
// works
var query = from t in table
where t.active= 1
join t2 in table
on t.parentID equals t2.ID into joined
from r in joined.DefaultIfEmpty() ...
But I can't figure out how to filter the right table. It seems like it should be something like this...
// does not work
var query = from t in table
join t2 in table
where t.field = 1
on t.parentID equals t2.ID into joined
from r in joined.DefaultIfEmpty() ...
(not valid... join can't have where). There is discussion of using multiple from clauses, but if I create more than one from clause, so I can add a where to the 2nd one, I can't figure out how to join the results of them into a new temporary table.
I can't just add a "where" after the join; the right table must be filtered first or matches will occur, and a where clause at the end would remove the row from the left table that I do want in the output. That is, the output should have rows where there's nothing matched from filtered right table. So I need to filter the right table before the join.
I think you are looking to do this:
var query = from t in table
join t2 in
(from t3 in table
where t3.field = 1
select t3)
on t.parentID equals t2.ID into joined
from r in joined.DefaultIfEmpty() ...
Another way is to use multiple from like this:
var query = from t in table
from t2 in table.Where(x => x.field = 1)
.Where(x => x.ID == t.parentID)
.DefaultIfEmpty()
select ....

How to design a SQL recursive query?

How would I redesign the below query so that it will recursively loop through entire tree to return all descendants from root to leaves? (I'm using SSMS 2008). We have a President at the root. under him are the VPs, then upper management, etc., on down the line. I need to return the names and titles of each. But this query shouldn't be hard-coded; I need to be able to run this for any selected employee, not just the president. This query below is the hard-coded approach.
select P.staff_name [Level1],
P.job_title [Level1 Title],
Q.license_number [License 1],
E.staff_name [Level2],
E.job_title [Level2 Title],
G.staff_name [Level3],
G.job_title [Level3 Title]
from staff_view A
left join staff_site_link_expanded_view P on P.people_id = A.people_id
left join staff_site_link_expanded_view E on E.people_id = C.people_id
left join staff_site_link_expanded_view G on G.people_id = F.people_id
left join facility_view Q on Q.group_profile_id = P.group_profile_id
Thank you, this was most closely matching what I needed. Here is my CTE query below:
with Employee_Hierarchy (staff_name, job_title, id_number, billing_staff_credentials_code, site_name, group_profile_id, license_number, region_description, people_id)
as
(
select C.staff_name, C.job_title, C.id_number, C.billing_staff_credentials_code, C.site_name, C.group_profile_id, Q.license_number, R.region_description, A.people_id
from staff_view A
left join staff_site_link_expanded_view C on C.people_id = A.people_id
left join facility_view Q on Q.group_profile_id = C.group_profile_id
left join regions R on R.regions_id = Q.regions_id
where A.last_name = 'kromer'
)
select C.staff_name, C.job_title, C.id_number, C.billing_staff_credentials_code, C.site_name, C.group_profile_id, Q.license_number, R.region_description, A.people_id
from staff_view A
left join staff_site_link_expanded_view C on C.people_id = A.people_id
left join facility_view Q on Q.group_profile_id = C.group_profile_id
left join regions R on R.regions_id = Q.regions_id
WHERE C.STAFF_NAME IS NOT NULL
GROUP BY C.STAFF_NAME, C.job_title, C.id_number, C.billing_staff_credentials_code, C.site_name, C.group_profile_id, Q.license_number, R.region_description, A.people_id
ORDER BY C.STAFF_NAME
But I am wondering what is the purpose of the "Employee_Hierarchy"? When I replaced "staff_view" in the outer query with "Employee_Hierarchy", it only returned one record = "Kromer". So when/where can we use "Employee_Hierarchy"?
See:
SQL Server - Simple example of a recursive CTE
MSDN: Recursive Queries using Common Table Expression
SQL Server recursive CTE (this seems pretty much like exactly what you are working on!)
Update:
A proper recursive CTE consist of basically three things:
an anchor SELECT to begin with; that can select e.g. the root level employees (where the Reports_To is NULL), or it can select any arbitrary employee that you define, e.g. by a parameter
a UNION ALL
a recursive SELECT statement that selects from the same, typically self-referencing table and joins with the recursive CTE being currently built up
This gives you the ability to recursively build up a result set that you can then select from.
If you look at the Northwind sample database, it has a table called Employees which is self-referencing: Employees.ReportsTo --> Employees.EmployeeID defines who reports to whom.
Your CTE would look something like this:
;WITH RecursiveCTE AS
(
-- anchor query; get the CEO
SELECT EmployeeID, FirstName, LastName, Title, 1 AS 'Level', ReportsTo
FROM dbo.Employees
WHERE ReportsTo IS NULL
UNION ALL
-- recursive part; select next Employees that have ReportsTo -> cte.EmployeeID
SELECT
e.EmployeeID, e.FirstName, e.LastName, e.Title,
cte.Level + 1 AS 'Level', e.ReportsTo
FROM
dbo.Employees e
INNER JOIN
RecursiveCTE cte ON e.ReportsTo = cte.EmployeeID
)
SELECT *
FROM RecursiveCTE
ORDER BY Level, LastName
I don't know if you can translate your sample to a proper recursive CTE - but that's basically the gist of it: anchor query, UNION ALL, recursive query