How to perform a LEFT JOIN in SQL Server between two SELECT statements? - sql

I have two SELECT statements in SQL Server like these:
(SELECT [UserID] FROM [User])
(SELECT [TailUser], [Weight] FROM [Edge] WHERE [HeadUser] = 5043)
I want to perform a LEFT JOIN between these two SELECT statements on [UserID] attribute and [TailUser] attribute. I want to join existent records in second query with the corresponding records in first query and NULL value for absent records. How can I do this?

SELECT * FROM
(SELECT [UserID] FROM [User]) a
LEFT JOIN (SELECT [TailUser], [Weight] FROM [Edge] WHERE [HeadUser] = 5043) b
ON a.UserId = b.TailUser

SELECT [UserID] FROM [User] u LEFT JOIN (
SELECT [TailUser], [Weight] FROM [Edge] WHERE [HeadUser] = 5043) t on t.TailUser=u.USerID

select *
from user
left join edge
on user.userid = edge.tailuser
and edge.headuser = 5043

Try this:
SELECT user.userID, edge.TailUser, edge.Weight
FROM user
LEFT JOIN edge ON edge.HeadUser = User.UserID
WHERE edge.HeadUser=5043
OR
AND edge.HeadUser=5043
instead of a WHERE clause.

Related

trying to modifying a multi join query with issues

I have a simplified query shown below, that does mulitple joins. I'm trying to add a field to be selected but I am unable to find a good way of joining it without changing the number of records that come up...
SELECT tblApp.AppID
,'Type' = tblRef.Label
,'Status' = tblRef2.Label
FROM (
(
(
tblApp LEFT JOIN tblAppExt ON tblApp.AppID = tblAppExt.AppID
) LEFT JOIN tblRef ON tblApp.AppTypeID = tblReferenceData.ID
) LEFT JOIN tblRef tblRef2 ON tblApp.AppStatusID = tblRef2.ID
)
As is - I'm getting 149 results, if I try to Join it in any way, I get like 10 time fold the number of records. All I'm hoping to do is be able to SELECt another field. I'm hoping to join tblAppExt2 that has AppID just like the other tables in the FROM part of the query, so my goal would basically be to do this:
SELECT tblApp.AppID
,'Type' = tblRef.Label
,'Status' = tblRef2.Label
,'NewField' = tblAppExt2.NewField
First thing to try is DISTINCT:
SELECT DISTINCT
tblApp.AppID
, [Type] = tblRef.Label
, [Status] = tblRef2.Label
, [NewField] = tblAppExt2.NewField
FROM tblApp
LEFT JOIN tblAppExt
ON tblApp.AppID = tblAppExt.AppID
LEFT JOIN tblRef
ON tblApp.AppTypeID = tblReferenceData.ID
LEFT JOIN tblRef tblRef2
ON tblApp.AppStatusID = tblRef2.ID
LEFT JOIN tblAppExt2.NewField
ON something = somethingElse ;
If that doesn't work, it means there are multiple different values for [NewField] and you'll need to tell it how to select the correct one. For example, to take the most recent [NewField] you can use a CTE with the ROW_NUMBER function:
; WITH AllRecords
AS (
SELECT DISTINCT
tblApp.AppID
, [Type] = tblRef.Label
, [Status] = tblRef2.Label
, [NewField] = tblAppExt2.NewField
, MyRank = ROW_NUMBER() OVER(PARTITION BY tblApp.ID ORDER BY tblAppExt2.DateEntered DESC)
FROM tblApp
LEFT JOIN tblAppExt
ON tblApp.AppID = tblAppExt.AppID
LEFT JOIN tblRef
ON tblApp.AppTypeID = tblReferenceData.ID
LEFT JOIN tblRef tblRef2
ON tblApp.AppStatusID = tblRef2.ID
LEFT JOIN tblAppExt2.NewField
ON something = somethingElse
)
SELECT *
FROM AllRecords
WHERE AllRecords.MyRank = 1 ;
You can use outer apply or correlated subquery :
SELECT tblApp.AppID, tblRef.Label as [Type], tblRef2.Label as [Status],
tappext.NewField
FROM tblApp tapp LEFT JOIN
tblAppExt tex
ON tapp.AppID = tex.AppID LEFT JOIN
tblRef tref
ON tapp.AppTypeID = tref.ID LEFT JOIN
tblRef tblRef2
ON tapp.AppStatusID = tblRef2.ID OUTER APPLY
( SELECT TOP (1) tappext.*
FROM tblAppExt2 tappext
WHERE tapp.AppID = AppID
ORDER BY ??
) tappext;

insert into select from inner join where not exists

I have this SQL Server code. Everything works except it duplicates rows with same RightsId and UserId. The where not exists clause is not working.
Any help is appreciated.
INSERT INTO dbo.UserAccessRights (Id, UserId, RightType, RightsId, CreatedOn, CreatedBy)
SELECT DISTINCT
NEWID(),
#changedUserId,
N'Process ' + #rightsTypeSuffix,
ptm.ProcessInstance_id,
getdate(),
#loggedInUserId
FROM
dbo.ProcessTeamMembers ptm WITH (NOLOCK)
INNER JOIN
dbo.Users u WITH (NOLOCK) ON ptm.TeamMemberProfile_id = u.ProfileID
AND u.Id = #changedUserId
AND ptm.TenantId = #tenantId
INNER JOIN
dbo.ProcessInstances p_i WITH (NOLOCK) ON p_i.Id = ptm.ProcessInstance_id
AND p_i.DeletedOn IS NULL
WHERE
NOT EXISTS (SELECT *
FROM UserAccessRights uar WITH (NOLOCK)
WHERE uar.UserId = #changedUserId
AND uar.RightsId = ptm.ProcessInstance_id)
Your duplicates are probably coming from within the query, rather than from existing rows in the table. Possibly, the problem is that the select distinct isn't doing anything -- because newid() is always unique.
My recommendation is to change the id column to have a default value of newid(). Then you don't need to insert it and the select distinct will work. Absent that, you can fix the query:
INSERT INTO dbo.UserAccessRights (Id, UserId, RightType, RightsId, CreatedOn, CreatedBy)
SELECT DISTINCT NEWID(), #changedUserId, N'Process ' + #rightsTypeSuffix,
ProcessInstance_id, getdate(), #loggedInUserId
FROM (SELECT DISTINCT ptm.ProcessInstance_id
FROM dbo.ProcessTeamMembers ptm WITH (NOLOCK) INNER JOIN
dbo.Users u WITH (NOLOCK)
ON ptm.TeamMemberProfile_id = u.ProfileID AND
u.Id = #changedUserId AND
ptm.TenantId = #tenantId INNER JOIN
dbo.ProcessInstances p_i WITH (NOLOCK)
ON p_i.Id = ptm.ProcessInstance_id AND
p_i.DeletedOn IS NULL
WHERE NOT EXISTS (SELECT 1
FROM UserAccessRights uar WITH (NOLOCK)
WHERE uar.UserId = #changedUserId AND
uar.RightsId = ptm.ProcessInstance_id
)
) t;
Hmmm, as I think about this, perhaps you should be using TOP 1 rather than SELECT DISTINCT. I'm not sure which columns cause the problem on the distinct, but you are inserting the same value in many columns, so more than one row might cause an issue.
Try the "Left Excluding Join" (See Visual Representation of SQL Joins) instead of the WHERE NOT EXISTS clause.
INSERT INTO dbo.UserAccessRights (Id, UserId, RightType, RightsId, CreatedOn, CreatedBy)
SELECT DISTINCT
NEWID(),
#changedUserId,
N'Process ' + #rightsTypeSuffix,
ptm.ProcessInstance_id,
getdate(),
#loggedInUserId
FROM
dbo.ProcessTeamMembers ptm
INNER JOIN
dbo.Users u ON ptm.TeamMemberProfile_id = u.ProfileID
AND u.Id = #changedUserId
AND ptm.TenantId = #tenantId
INNER JOIN
dbo.ProcessInstances p_i ON p_i.Id = ptm.ProcessInstance_id
AND p_i.DeletedOn IS NULL
LEFT JOIN UserAccessRights uar
ON uar.UserId = u.Id
AND uar.RightsId = ptm.ProcessInstance_id
WHERE
uar.Id IS NULL -- Replace with the actual pkey on UserAccessRights if not Id

SQL Server Conditional Join instead of WHERE .. IN .. clauses

SELECT A.Name, H.Name as BookedBy
FROM dbo.vwAllLoads A WITH (NOEXPAND)
LEFT JOIN dbo.SystemInfo H
ON (A.BookedByUserID = H.GlobalNetUserID)
WHERE ((A.CustomerID IN (SELECT UCR.CustomerID
FROM dbo.UserCustomerRelations UCR
WHERE UCR.UserID IN
(SELECT UserID FROM #PodUsers)
OR H.GlobalUserID IN
(SELECT UserID FROM #PodUsers)))
Now I filter data using above where clause. How can I accomplish the same using joins or in a better way?
Please help
Assuming your query is something like:
select a.*
from a
where A.CustomerID IN (SELECT UCR.CustomerID
FROM dbo.UserCustomerRelations UCR
WHERE UCR.UserID IN (SELECT UserID FROM #PodUsers) OR
UCR.GlobalNetUserID IN (SELECT UserID FROM #PodUsers)
-----------------------------^ was `H`, I'm assuming is `UCR`
)
Then the following should be an equivalent query using joins:
select distinct a.*
from a join
dbo.UserCustomerRelations ucr
on A.CustomerID = ucr.CustomerID join
#PodUsers pu
on ucr.UserId = pu.UserId or ucr.UserId = ucr.GlobalNetUserID = pu.UserId;
The distinct would be unnecessary if you know that the joins do not produce multiple rows
I guess something like this:
INNER JOIN [dbo].[UserCustomerRelations] UCR
ON A.[CustomerID] = UCR.[CustomerID]
INNER JOIN #PodUsers PU
ON UCR.[CustomerID] = PD.[UserID]
OR H.[GlobalNetUserID] = PD.[UserID]

Delete statement SQL joins

Can anyone please tell me how to write a delete statement for the following query:
SELECT a.UserID, b.UserEmailAddress
FROM tblUserProgramme AS a LEFT OUTER JOIN
tblUser AS b ON b.UserID = a.UserID LEFT OUTER JOIN
tblWorkGroup AS c ON c.WorkGroupID = b.WorkGroupID
WHERE(a.ProgrammeID = 59) AND (a.UserID NOT IN
(SELECT UserID FROM tblUser AS a WHERE (WorkGroupID IN
(SELECT WorkGroupID FROM tblWorkGroup WHERE
(WorkGroupName LIKE '%Insight%') OR (WorkGroupName LIKE '%Other%')))))
AND (b.UserEmailAddress NOT IN
(SELECT email FROM tmpUsers))
ORDER BY b.UserEmailAddress
SERVER is SQL Server 2005
Query would be
Delete from
(
SELECT a.UserID, b.UserEmailAddress
FROM tblUserProgramme AS a LEFT OUTER JOIN
tblUser AS b ON b.UserID = a.UserID LEFT OUTER JOIN
tblWorkGroup AS c ON c.WorkGroupID = b.WorkGroupID
WHERE(a.ProgrammeID = 59) AND (a.UserID NOT IN
(SELECT UserID FROM tblUser AS a WHERE (WorkGroupID IN
(SELECT WorkGroupID FROM tblWorkGroup WHERE (WorkGroupName LIKE
'%Insight%') OR (WorkGroupName LIKE '%Other%'))))) AND (b.UserEmailAddress NOT IN
(SELECT email FROM tmpUsers))
ORDER BY b.UserEmailAddress
) a
Syntax is DB specific..
For most of tha databases this should work , if you want to delete from tblUserProgramme
DELETE A
FROM tblUserProgramme AS a
.....
In general, in SQL Server, you can delete all records which match a given SQL query as follows, provided your SELECT only returns columns from a single table:
DELETE x
FROM
(
-- Any query which returns data from a single table, that you wish to delete
) x;
Or, using a CTE:
;WITH x as
(
-- Any query which returns data from a single table, that you wish to delete
)
DELETE x;
Thank you all for your quick answers:) There were a quite a few answers right, but had to pick the first one:)
As Joe G Joseph has mentioned,
this is what i did
DELETE a
from dbo.tblUserProgramme a
LEFT OUTER JOIN tblUser b ON b.UserID = a.UserID
LEFT OUTER JOIN tblWorkGroup c ON c.WorkGroupID = b.WorkGroupID
where a.ProgrammeID = 59 AND
a.UserID NOT IN (SELECT UserID FROM tblUser a WHERE a.WorkGroupID IN
(SELECT WorkGroupID FROM tblWorkGroup
WHERE WorkGroupName like '%Insight%' OR WorkGroupName like '%Other%'))
AND b.UserEmailAddress NOT IN(SELECT email FROM tmpUsers)

Converting nested Selects in WHERE .. OR .. to INNER JOINS

How would I convert the following to use INNER JOIN rather than nested SELECT?
SELECT
[Name].[NameValueID],
[Name].[NameTypeID],
[Name].[NameID],
[Name].[Value]
FROM [Name]
WHERE Name.NameTypeID IN ( SELECT NameTypeID FROM #tbNameType )
OR Name.NameID IN ( SELECT NameID FROM #tbName)
This one's tricky because it's an "OR" condition rather than an "AND". But I think this would do it:
SELECT
[Name].[NameValueID],
[Name].[NameTypeID],
[Name].[NameID],
[Name].[Value]
FROM [Name]
INNER JOIN ( SELECT NameTypeID FROM #tbNameType ) t ON t.NameTypeID=Name.NameTypeID
UNION
SELECT
[Name].[NameValueID],
[Name].[NameTypeID],
[Name].[NameID],
[Name].[Value]
FROM [Name]
INNER JOIN ( SELECT NameID FROM #tbName) t ON t.NameID = Name.NameID
SELECT DISTINCT
Name.NameValueID,
Name.NameTypeID,
Name.NameID,
Name.Value
FROM
Name
LEFT JOIN #tbNameType a ON a.NameTypeID=Name.NameTypeID
LEFT JOIN #tbName b ON b.NameID=Name.NameID
WHERE a.NameTypeID IS NOT NULL OR b.NameID IS NOT NULL