Convert right outer join to Linq query in EF - sql-server

I want to convert below SQL query to linq query but I confused:
SELECT *
FROM dbo.Vahed
INNER JOIN dbo.VahedMahsol ON dbo.Vahed.VahedId = dbo.VahedMahsol.VahedId
RIGHT OUTER JOIN dbo.Mahsol ON dbo.VahedMahsol.MahsolId = dbo.Mahsol.MahsolId
I wrote this code:
vaheds =
(
from i in db.spGetVahedByWhatWhere(what, wherestr, int.Parse(whattype), new Guid(shahrid))
join gr in db.GorohSenfis on i.GorohSenfiId equals gr.GorohSenfiID
join ct in db.Contacts on i.VahedId equals ct.VahedId
join vm in db.VahedMahsols on i.VahedId equals vm.VahedId
select i
)
.ToList();
but i don't know how to convert
RIGHT OUTER JOIN dbo.Mahsol ON dbo.VahedMahsol.MahsolId = dbo.Mahsol.MahsolId
to linq query.

First of all you can rewrite your SQL query to use a LEFT OUTER JOIN instead of a RIGHT OUTER JOIN (because this is easier to convert to LINQ):
SELECT *
FROM dbo.Mahsol
LEFT OUTER JOIN dbo.VahedMahsol ON dbo.Mahsol.MahsolId = dbo.VahedMahsol.MahsolId
INNER JOIN dbo.Vahed ON dbo.VahedMahsol.VahedId = dbo.Vahed.VahedId
Now you can convert the query above in LINQ like this:
vaheds = (
from m in db.Mahsols
join vm1 in db.VahedMahsols on m.MahsolId equals v.MahsolId into vmgroup
from vm in vmgroup.DefaultIfEmpty()
join i in db.spGetVahedByWhatWhere(what, wherestr, int.Parse(whattype), new Guid(shahrid))
on vm.VahedId equals i.VahedId
join gr in db.GorohSenfis on i.GorohSenfiId equals gr.GorohSenfiID
join ct in db.Contacts on i.VahedId equals ct.VahedId
select i
).ToList();
I have no way of testing this, but I hope it works.

Related

Make one-to-one relation between two tables that have one-to-many relation in SQL

I have these queries :
SELECT
dbo.Lines.Unit, dbo.Lines.LineNumber, dbo.Lines.DocumentNumber,
dbo.BaseMaterials.Name AS MaterialName,
dbo.MaterialDescriptions.Name AS MaterialDescription,
dbo.MaterialDescriptions.Description,
dbo.MaterialScopes.ScopeName, dbo.MaterialScopeObjectNames.ObjectName,
dbo.MaterialDescriptions.Size1, dbo.MaterialDescriptions.Size2,
dbo.MaterialDescriptions.ItemCode, dbo.Materials.Quantity,
dbo.Materials.Discipline, dbo.Materials.Id, dbo.Lines.Id AS LineId
FROM
dbo.Materials
INNER JOIN
dbo.Lines ON dbo.Materials.LineId = dbo.Lines.Id
INNER JOIN
dbo.BaseMaterials ON dbo.Lines.BaseMaterialId = dbo.BaseMaterials.Id
INNER JOIN
dbo.MaterialDescriptions ON dbo.Materials.MaterialDescriptionId = dbo.MaterialDescriptions.Id
INNER JOIN
dbo.MaterialScopes ON dbo.MaterialDescriptions.MaterialScopeId = dbo.MaterialScopes.Id
INNER JOIN
dbo.MaterialScopeObjectNames ON dbo.MaterialDescriptions.MaterialScopeObjectId = dbo.MaterialScopeObjectNames.Id
It returns 16000 records. I have another tables with joints name that has a relation with material table on lineId every material can have multi joints so my query when I add joints table is like this :
SELECT
dbo.Lines.Unit, dbo.Lines.LineNumber, dbo.Lines.DocumentNumber,
dbo.BaseMaterials.Name AS MaterialName,
dbo.MaterialDescriptions.Name AS MaterialDescription,
dbo.MaterialDescriptions.Description, dbo.MaterialScopes.ScopeName,
dbo.MaterialScopeObjectNames.ObjectName, dbo.MaterialDescriptions.Size1,
dbo.MaterialDescriptions.Size2, dbo.MaterialDescriptions.ItemCode,
dbo.Materials.Quantity, dbo.Materials.Discipline, dbo.Materials.Id,
dbo.Lines.Id AS LineId, dbo.Joints.TestPackageId
FROM
dbo.Materials
INNER JOIN
dbo.Lines ON dbo.Materials.LineId = dbo.Lines.Id
INNER JOIN
dbo.BaseMaterials ON dbo.Lines.BaseMaterialId = dbo.BaseMaterials.Id
INNER JOIN
dbo.MaterialDescriptions ON dbo.Materials.MaterialDescriptionId = dbo.MaterialDescriptions.Id
INNER JOIN
dbo.MaterialScopes ON dbo.MaterialDescriptions.MaterialScopeId = dbo.MaterialScopes.Id
INNER JOIN
dbo.MaterialScopeObjectNames ON dbo.MaterialDescriptions.MaterialScopeObjectId = dbo.MaterialScopeObjectNames.Id
INNER JOIN
dbo.Joints ON dbo.Materials.LineId = dbo.Joints.LineId
As you can see in the last line i make a join between joints and materials to access the testpackageid column in joints table .but my result returns 220000records .How can i change the join type i mean left or right to just returns 16000 records with its testpackageId
You can't using JOIN. However, you can using CROSS APPLY:
FROM . . .
dbo.MaterialScopeObjectNames
ON dbo.MaterialDescriptions.MaterialScopeObjectId = dbo.MaterialScopeObjectNames.Id CROSS APPLY
(SELECT TOP 1 j.*
FROM dbo.Joints j
WHERE dbo.Materials.LineId = j.LineId
) J
Normally, you would include an ORDER BY when using TOP so you have some control over the row being returned.
Also note that the use of table aliases makes the query easier to write and to read.
You can get it very easily with just a subquery. Leave your query as it is, and add a subquery to get that information from Joints.
SELECT dbo.Lines.Unit, dbo.Lines.LineNumber, dbo.Lines.DocumentNumber, dbo.BaseMaterials.Name AS MaterialName, dbo.MaterialDescriptions.Name AS MaterialDescription, dbo.MaterialDescriptions.Description,
dbo.MaterialScopes.ScopeName, dbo.MaterialScopeObjectNames.ObjectName, dbo.MaterialDescriptions.Size1, dbo.MaterialDescriptions.Size2, dbo.MaterialDescriptions.ItemCode, dbo.Materials.Quantity,
dbo.Materials.Discipline, dbo.Materials.Id, dbo.Lines.Id AS LineId,
(select top 1 dbo.Joints.TestPackageId from dbo.Joints where dbo.Joints.LineId = dbo.Materials.LineId)
FROM dbo.Materials INNER JOIN
dbo.Lines ON dbo.Materials.LineId = dbo.Lines.Id INNER JOIN
dbo.BaseMaterials ON dbo.Lines.BaseMaterialId = dbo.BaseMaterials.Id INNER JOIN
dbo.MaterialDescriptions ON dbo.Materials.MaterialDescriptionId = dbo.MaterialDescriptions.Id INNER JOIN
dbo.MaterialScopes ON dbo.MaterialDescriptions.MaterialScopeId = dbo.MaterialScopes.Id INNER JOIN
dbo.MaterialScopeObjectNames ON dbo.MaterialDescriptions.MaterialScopeObjectId = dbo.MaterialScopeObjectNames.Id

groupby in view of sql returns aggregate error

I am trying to create a view with this query as you can see here:
SELECT dbo.Lines.LineNumber, dbo.Lines.DocumentNumber, dbo.Joints.JointNumber, dbo.Joints.JointSize, dbo.Joints.ShopField, dbo.Joints.WPS, dbo.WeldDetails.StateStep2 AS WeldState, dbo.Welds.WeldNumber,
dbo.FitUps.FitUpNumber, MAX(dbo.WeldDetails.Id) AS WeldDetailId, MAX(dbo.FitUpDetails.Id) AS FitupDetailId, dbo.Joints.Id AS JointId, dbo.Ends.Name, dbo.Joints.THK, dbo.FitUpDetails.StateStep2 AS FitupState,
dbo.Joints.Revision, dbo.Joints.Note
FROM dbo.FitUps INNER JOIN
dbo.Welds INNER JOIN
dbo.Joints INNER JOIN
dbo.WeldDetails ON dbo.Joints.Id = dbo.WeldDetails.JointId INNER JOIN
dbo.FitUpDetails ON dbo.Joints.Id = dbo.FitUpDetails.JointId ON dbo.Welds.Id = dbo.WeldDetails.WeldId ON dbo.FitUps.Id = dbo.FitUpDetails.FitUpId INNER JOIN
dbo.Lines ON dbo.Joints.LineId = dbo.Lines.Id INNER JOIN
dbo.Ends ON dbo.Joints.EndId = dbo.Ends.Id
GROUP BY dbo.Joints.Id
But when i want to save the view i get this error :
Here is a part of my data :
Every joint id can have multi fitupdetailid and welddetailid in my view i want just show the maximum value of fitupdetailid and welddetailid of my joint.
I rewrote your query with a more readable join structure than what your GUI spit out. This should run for you and fix your error. Whether the results are what you want or not depends on your data. You may also want to re-order the grouping to group how you want, hierarchically. But all of those columns will need to be in the grouping in one form or another.
SELECT
dbo.Lines.LineNumber,
dbo.Lines.DocumentNumber,
dbo.Joints.JointNumber,
dbo.Joints.JointSize,
dbo.Joints.ShopField,
dbo.Joints.WPS,
dbo.WeldDetails.StateStep2 AS WeldState,
dbo.Welds.WeldNumber,
dbo.FitUps.FitUpNumber,
MAX(dbo.WeldDetails.Id) AS WeldDetailId,
MAX(dbo.FitUpDetails.Id) AS FitupDetailId,
dbo.Joints.Id AS JointId,
dbo.Ends.Name,
dbo.Joints.THK,
dbo.FitUpDetails.StateStep2 AS FitupState,
dbo.Joints.Revision,
dbo.Joints.Note
FROM
dbo.FitUps
INNER JOIN dbo.FitUpDetails ON dbo.FitUps.Id = dbo.FitUpDetails.FitUpId
INNER JOIN dbo.Joints ON dbo.Joints.Id = dbo.FitUpDetails.JointId
INNER JOIN dbo.WeldDetails ON dbo.Joints.Id = dbo.WeldDetails.JointId
INNER JOIN dbo.Welds ON dbo.Welds.Id = dbo.WeldDetails.WeldId
INNER JOIN dbo.Lines ON dbo.Joints.LineId = dbo.Lines.Id
INNER JOIN dbo.Ends ON dbo.Joints.EndId = dbo.Ends.Id
GROUP BY
dbo.Lines.LineNumber,
dbo.Lines.DocumentNumber,
dbo.Joints.JointNumber,
dbo.Joints.JointSize,
dbo.Joints.ShopField,
dbo.Joints.WPS,
dbo.WeldDetails.StateStep2,
dbo.Welds.WeldNumber,
dbo.FitUps.FitUpNumber,
dbo.Joints.Id,
dbo.Ends.Name,
dbo.Joints.THK,
dbo.FitUpDetails.StateStep2,
dbo.Joints.Revision,
dbo.Joints.Note

Convert nested join sql query to nested join LINQ

I am trying to convert nested join sql query to linq. I need some help to convert the query into linq. I am using vb.net.
This is my sql query:
SELECT tblJobSkillMatrix_JS.fldJobTitleID,
tblRSCFMainLevel.fldRSCFMainLevel,
tblRSCFSkill.fldRCSFSkill,
tblSkillLevelDefinition.fldSkillLevelNum,
tblJobSkillMatrix_JS.fldPriorityJobSkill
FROM ((tblJobSkillMatrix_JS
INNER JOIN (tblRSCFMainLevel
INNER JOIN tblRSCFSkill
ON tblRSCFMainLevel.fldRSCFMainLevelID = tblRSCFSkill.fldRSCFMainLevelID)
ON tblJobSkillMatrix_JS.fldRSCFSkillID = tblRSCFSkill.fldRSCFSkillID)
INNER JOIN tblSkillLevelDefinition ON
tblJobSkillMatrix_JS.fldSkillLevelID = tblSkillLevelDefinition.fldSkillLevelID)
INNER JOIN tblRSCFSkillGroupLevel ON
(tblRSCFSkillGroupLevel.fldRSCFSkillGroupLevelID = tblRSCFSkill.fldRSCFSkillGroupLevelID)
AND (tblRSCFMainLevel.fldRSCFMainLevelID = tblRSCFSkillGroupLevel.fldRSCFMainLevelID)
WHERE (tblJobSkillMatrix_JS.fldJobTitleID='F74F5BCA-F33A-4AE1-9825-16B05AB274F4')
AND (tblRSCFMainLevel.fldRSCFMainLevel='People skills')
ORDER BY tblJobSkillMatrix_JS.fldPriorityJobSkill;

Want to convert 3 rows in 3 columns with inner join in SQL Server

I have a result set like this
And query for this result set is
SELECT
dt.GangName, u.UserFullName,dt.Designation, v.RegNo,
dt.SignInTime, dt.SignOutTime, z.ZoneName
FROM
DutyRoosterTeam dt
INNER JOIN
DutyRooster dr ON dr.DutyRoosterID = dt.DutyRoosterID
INNER JOIN
Users u ON u.UserId = dt.UserID
INNER JOIN
Vehicle v ON v.VehicleId = dt.MTLID
INNER JOIN
Zone z ON z.ZoneId = dt.ZoneID
But I want result set like this
My copy-pasta-fu is strong. Take a look at the solution provided by bluefeet here:
Convert Rows to columns using 'Pivot' in SQL Server

TSQL Inner select using outer join

I have a query that is working for the most part until I had to add the inner select for "Trainers".
As you can see in the code below, I am trying to get all of the trainers for each of the segment ID's.
I am getting an error on the first inner selects where clause WHERE trn.segmentID = tes.teSegmentID saying that tes.teSegmentID is not defined.
Is there another way to approach this query in order to get the trainers like I am trying to accomplish?
SELECT *,
(SELECT e2.[FirstName] AS trainerFirst,
e2.[LastName] AS trainerLast
FROM BS_Training_Trainers AS trn
LEFT OUTER JOIN
employeeTable AS e2
ON trn.trainerEmpID = e2.EmpID
WHERE trn.segmentID = tes.teSegmentID
FOR XML PATH ('trainer'), TYPE, ELEMENTS, ROOT ('trainers'))
FROM dbo.BS_TrainingEvents AS a
WHERE a.trainingEventID IN (SELECT tes.trainingEventID
FROM dbo.BS_TrainingEvent_Segments AS tes
INNER JOIN
dbo.BS_TrainingEvent_SegmentDetails AS tesd
ON tesd.segmentID = tes.teSegmentID
INNER JOIN
dbo.BS_LocaleCodes AS locale
ON locale.localeID = tesd.localeID
WHERE locale.location = 'Baltimore');
It seems like you're taking the scenic route towards this:
SELECT a.*,
X.[FirstName],
X.[LastName]
FROM dbo.BS_TrainingEvents AS a
LEFT OUTER JOIN (SELECT e2.[FirstName], e2.[LastName], locale.location FROM dbo.BS_TrainingEvent_Segments AS tes
INNER JOIN dbo.BS_Training_Trainers AS trn ON trn.segmentID = tes.teSegmentID
INNER JOIN dbo.BS_TrainingEvent_SegmentDetails AS tesd ON tesd.segmentID = tes.teSegmentID
INNER JOIN dbo.BS_LocaleCodes AS locale ON locale.localeID = tesd.localeID
LEFT OUTER JOIN employeeTable AS e2 ON trn.trainerEmpID = e2.EmpID) AS X ON a.trainingEventID = X.trainingEventID
WHERE X.location = 'Baltimore';
Not sure if I got all those joins right, it was hard to decode from all the nesting you have going on.
If I have guessed table relationships from their names correctly, the only way to solve this is to reference the same filtering condition twice: first, in the XML generation part, and second in the outer level of the query:
with cte as (
select distinct tes.trainingEventID, tes.teSegmentID
from dbo.BS_TrainingEvent_Segments AS tes
INNER JOIN dbo.BS_TrainingEvent_SegmentDetails AS tesd ON tesd.segmentID = tes.teSegmentID
INNER JOIN dbo.BS_LocaleCodes AS locale ON locale.localeID = tesd.localeID
WHERE locale.location = 'Baltimore'
)
SELECT a.*, (
SELECT e2.[FirstName] AS trainerFirst, e2.[LastName] AS trainerLast
FROM BS_Training_Trainers AS trn
LEFT OUTER JOIN employeeTable AS e2 ON trn.trainerEmpID = e2.EmpID
inner join cte c on trn.segmentID = c.teSegmentID
FOR XML PATH ('trainer'), TYPE, ELEMENTS, ROOT ('trainers')
)
FROM dbo.BS_TrainingEvents AS a
where exists (select 0 from cte c where c.testrainingEventID = a.trainingEventID);
It's difficult to tell whether this is completely correct, of course, but I hope you get the idea.
Oh yes, and if you would have an event with multiple Baltimore segments, you will never be able to tell which trainer takes which one. But you can always add more data into XML to resolve this.

Resources