WHERE clause not functioning as expected - sql

I am trying to join some tables to receive some data and it is not working as expected. Here is my query:
SELECT USR.PK_User AS PKUser
,USR.NAME AS NAME
FROM [User] USR
LEFT JOIN aspnet_Users ASPU ON USR.NAME = ASPU.UserName
LEFT JOIN aspnet_UsersInRoles ASPUIR ON ASPU.UserId = ASPUIR.UserId
WHERE ASPUIR.RoleId = 'E8700479-902A-42F1-A500-4FA02CAC356C'
Nothing is being returned from this query. But if I do:
SELECT * FROM [aspnet_UsersInRoles] WHERE RoleId = 'E8700479-902A-42F1-A500-4FA02CAC356C'
I get 76 selected rows. If I just do:
SELECT USR.PK_User AS PKUser
,USR.NAME AS NAME
FROM [User] USR
LEFT JOIN aspnet_Users ASPU ON USR.NAME = ASPU.UserName
LEFT JOIN aspnet_UsersInRoles ASPUIR ON ASPU.UserId = ASPUIR.UserId
I get the expected rows returned. Additionally, if I add:
WHERE ASPUIR.RoleId IS NULL
I get rows back.
What am I doing wrong?

You need the condition in the ON not the WHERE.
Otherwise you just make it back into an inner join effectively.
SELECT USR.PK_User AS PKUser,
USR.NAME AS NAME
FROM [User] USR
LEFT JOIN aspnet_Users ASPU
ON USR.NAME = ASPU.UserName
LEFT JOIN aspnet_UsersInRoles ASPUIR
ON ASPU.UserId = ASPUIR.UserId
AND ASPUIR.RoleId = 'E8700479-902A-42F1-A500-4FA02CAC356C'

Try this:-
SELECT USR.PK_User AS PKUser,
USR.NAME AS NAME
FROM [User] USR
LEFT JOIN aspnet_Users ASPU
ON USR.NAME = ASPU.UserName
LEFT JOIN aspnet_UsersInRoles ASPUIR
ON ASPU.UserId = ASPUIR.UserId
AND ASPUIR.RoleId = 'E8700479-902A-42F1-A500-4FA02CAC356C'

Related

Full outer join a table to another table that's being left joined to the main table

So i've got hte below code that works for the most part but when I'm trying to bring in the last table i cant get the expected results.
SELECT
CASE
WHEN CCO.Account_Manager__c IS NULL THEN Opp.OwnerId ELSE CCO.Account_Manager__c
END AS AccountManager,
CCO.Account_Associate__c as ClientOfficeAccountAssociate,
Opp.OwnerId as AccountOwnerId,
CCO.Account_Manager__c as ClientOfficeAM,
ACC.Name as AccountName,
OPP.Forum_Monthly_Recurring_Revenue_MRR__c,
PAYG.Revenue
LEFT JOIN `round-cacao-234512.salesforce.Opportunity` as OPP
ON OPP.Id = Split.OpportunityId AND OPP.OwnerId = Split.SplitOwnerId
LEFT JOIN `round-cacao-234512.salesforce.Account` as ACC
on ACC.Id = OPP.AccountId
LEFT JOIN `round-cacao-234512.salesforce.User` as USER
ON USER.Id = OPP.OwnerId
LEFT JOIN `round-cacao-234512.salesforce_df.Company_Client_Office__c` as CCO
ON CCO.Opportunity__c = OPP.Id
LEFT JOIN `round-cacao-234512.salesforce.Client_Office_Intranet__c` as COI
ON COI.Id = CCO.Client_Office_Intranet__c
LEFT JOIN `round-cacao-234512.salesforce.RecordType` as RT
ON RT.Id = OPP.RecordTypeId
LEFT JOIN `commercial-analysis.materialised.2022AMDashForumRRQuotas` as Quota
on Quota.AccountID = CCO.Account_Manager__c OR Quota.AccountID = Opp.OwnerId
LEFT JOIN `commercial-analysis.2022_AM_Territory.FPAYG_Quotas` as PAYGQuota
on PAYGQuota.ClientOffice = COI.Name
Full Outer JOIN `round-cacao-234512.materialised.2022AMDashPAYGRevenue` PAYGRev
on PAYGRev.ClientOffice = COI.Name
So my last table round-cacao-234512.materialised.2022AMDashPAYGRevenue will be joined on clientoffice but will also have client offices that don't appear in COI, so I want those to come in with nulls on all the values that don't match up.
Hope that makes sense

How to only run left join when the variable is not null?

I'm trying to simplify my stored procedure and I have one that is only using left join based on the user id that is passed in. If the user id is null, don't do left join, but if it is null, left join it with another table. How should I re-write it ? Thank you
CREATE OR ALTER PROCEDURE [dbo].[GetRoom]
#RoomId UNIQUEIDENTIFIER NULL,
#UserId UNIQUEIDENTIFIER
AS
BEGIN
IF (#UserId IS NULL)
BEGIN
SELECT r.Id, r.DisplayName
FROM Room r
INNER JOIN Game g ON r.GameId = g.Id
INNER JOIN ProfileDuplicated pd ON r.HostedById = pd.Id
WHERE r.Id = #RoomId
END
ELSE
SELECT
r.Id, r.DisplayName,
ru.Description, -- this is coming from the left join table
ru.Tags -- from left join table
FROM Room r
INNER JOIN Game g ON r.GameId = g.Id
INNER JOIN ProfileDuplicated pd ON r.HostedById = pd.Id
LEFT JOIN RoomUser ru ON ru.RoomId = r.Id
WHERE r.Id = #RoomId AND ru.UserId = #UserId
END
Currently your stored procedure return different number columns depending on the #UserId.
You may remove the IF condition, and combined it as one single query by moving ru.UserId = #UserId to ON condition. This will make it a true LEFT JOIN to table RoomUser.
This will means it always return 4 columns as result
SELECT r.Id,
r.DisplayName,
ru.Description,
ru.Tags
FROM Room r
INNER JOIN Game g ON r.GameId = g.Id
INNER JOIN ProfileDuplicated pd ON r.HostedById = pd.Id
LEFT JOIN RoomUser ru ON ru.RoomId = r.Id
AND ru.UserId = #UserId
WHERE r.Id = #RoomId
Try something like below,
SELECT
r.Id, r.DisplayName,
ru.Description, -- this is coming from the left join table
ru.Tags -- from left join table
FROM Room r
INNER JOIN Game g ON r.GameId = g.Id
INNER JOIN ProfileDuplicated pd ON r.HostedById = pd.Id
LEFT JOIN RoomUser ru ON ru.RoomId = r.Id
AND r.Id IS NOT NULL
AND r.Id = #RoomId
AND ru.UserId IS NOT NULL
AND ru.UserId = #UserId
You can use ISNULL function to check the NULL value of the parameter. (Assuming ru.userId will not be NULL)
WHERE r.Id = #RoomId AND
ru.UserId = ISNULL(#UserId, ru.UserId)

Query returns no records

Hello i am making schema for purchasing orders these orders can be ordered by certain user and then received by another user.
so i created the below schema.
Schema
The issue is when UserID column in PurchaseOrders and Deliveries tables has different values the query returns no records.
Query
SELECT
dbo.Users.FirstName,
dbo.Users.LastName,
dbo.PurchaseOrders.PurchaseOrderDate,
dbo.Deliveries.ExpectedDeliveryDate,
dbo.Deliveries.ActualDeliveryDate
FROM dbo.PurchaseOrders
INNER JOIN dbo.Users
ON dbo.PurchaseOrders.UserID = dbo.Users.UserID
INNER JOIN dbo.Deliveries
ON dbo.PurchaseOrders.PurchaseOrderID = dbo.Deliveries.PurchaseOrderID
AND dbo.Users.UserID = dbo.PurchaseOrders.UserID
AND dbo.Users.UserID = dbo.Deliveries.UserID
You need two different joins to Users. You also need to learn to use table aliases:
SELECT pu.FirstName as purchase_FirstName, pu.LastName as purchase_LastName,
du.FirstName as delivery_FirstName, du.LastName as delivery_LastName,
po.PurchaseOrderDate,
d.ExpectedDeliveryDate, d.ActualDeliveryDate
FROM dbo.PurchaseOrders po JOIN
dbo.Deliveries d
ON po.PurchaseOrderID = d.PurchaseOrderID JOIN
dbo.Users pu
ON p.UserID = pu.UserID JOIN
dbo.Users du
ON d.UserId = du.UserId;
Your query returns no records because of this condition:
AND dbo.Users.UserID = dbo.PurchaseOrders.UserID
AND dbo.Users.UserID = dbo.Deliveries.UserID
This obviously means that dbo.PurchaseOrders.UserID = dbo.Deliveries.UserID. So, if this is not true, then no records match the condition.
When you use Inner Join, if the data doesnt match, you will not get any records. You need to use LEFT JOIN and also the second join doesnt need condition with user id. Try the below query.
SELECT
dbo.Users.FirstName,
dbo.Users.LastName,
dbo.PurchaseOrders.PurchaseOrderDate,
dbo.Deliveries.ExpectedDeliveryDate,
dbo.Deliveries.ActualDeliveryDate
FROM dbo.PurchaseOrders
INNER JOIN dbo.Users
ON dbo.PurchaseOrders.UserID = dbo.Users.UserID
LEFT JOIN dbo.Deliveries
ON dbo.PurchaseOrders.PurchaseOrderID = dbo.Deliveries.PurchaseOrderID

SQL Server : JOIN query

I'm newbie in SQL Server and I need some help with SQL Server and JOIN method.
My code is:
SELECT TOP 1000
p.value AS userposition,
p2.value AS usercell,
t.id
FROM
[es] t
JOIN
[user] u ON t.user_uid = u.uid
JOIN
[user] su ON u.superior_uid = su.uid
JOIN
[user_params] up ON t.user_uid = up.user_uid
LEFT JOIN
[params] p ON up.param_id = p.id AND p.name_id = 1
JOIN
[user_params] up2 ON t.user_uid = up2.user_uid
LEFT JOIN
[params] p2 ON up2.param_id = p2.id AND p.name_id = 2
but it returns duplicated records. I want them just as many as rows in [es] table. In MySQL I would use GROUP BY t.id, but in SQL Server that method doesn't work.
Thanks in advance.
EDIT (clarification):
Thank you for your replies. Maybe I should describe my tables structure and what I need to display.
Table [ES]
[id],[user_uid],[more_data]
Table [User]
[uid],[superior_uid],[more_data]
Table [UserParams]
[id],[user_uid],[param_id]
Table [Params]
[id],[param_id],[value]
Now what I need is to get all records from [ES] add user data from [User] add his superior data on [User][superior_uid] which is also an [User] record, add [Params] with [Params][name_id] = 1 as value1 AND add [Params] with [Params][name_id] = 2 as value2 ... through [UserParams] if exists.
I think the problem is with JOIN or GROUP BY. [ES] records with users has no [UserParams] are shown only once, but those with [UserParams] are doubled.I tried LEFT OUTER JOIN but it doesn't work. :(
How about
SELECT DISTINCT TOP 1000
p.value AS userposition,
p2.value AS usercell,
t.id
FROM [es] t
JOIN [user] u ON t.user_uid = u.uid
JOIN [user] su ON u.superior_uid = su.uid
JOIN [user_params] up ON t.user_uid = up.user_uid
LEFT JOIN [params] p ON up.param_id = p.id AND p.name_id = 1
JOIN [user_params] up2 ON t.user_uid = up2.user_uid
LEFT JOIN [params] p2 ON up2.param_id = p2.id AND p.name_id = 2
ORDER BY (whichever rows that you want it to be ordered by) ?
all of your columns need to be in the group by, or part of an aggregate function
p.value AS userposition, #group by or agg func
p2.value AS usercell, #group by or agg func
t.id #group by
Wouldnt be certain without knowing what p.value and p2.value actually mean
Not to sure about the joins but I guess you know what you doing, to select distinct row you can use row_number() function as below
SELECT userposition
,usercell
,id
FROM (
SELECT TOP 1000
p.value AS userposition
,p2.value AS usercell
,t.id
,ROW_NUMBER() OVER (PARTITION BY t.user_uid ORDER BY t.user_uid) rn
FROM [es] t
INNER JOIN [user] u ON t.user_uid = u.[uid]
INNER JOIN [user] su ON u.superior_uid = su.[uid]
INNER JOIN [user_params] up ON t.user_uid = up.user_uid
LEFT JOIN [params] p ON up.param_id = p.id AND p.name_id = 1
INNER JOIN [user_params] up2 ON t.user_uid = up2.user_uid
LEFT JOIN [params] p2 ON up2.param_id = p2.id AND p.name_id = 2
) A
WHERE A.rn = 1
You can get rid of the last 2 joins by combining them, use DISTINCT to not get repeated entries, and use ORDER BY to sort it.
SELECT DISTINCT TOP 1000
p.value AS userposition,
p2.value AS usercell,
t.id
FROM [es] t
JOIN [user] u ON t.user_uid = u.uid
JOIN [user] su ON u.superior_uid = su.uid
JOIN [user_params] up ON t.user_uid = up.user_uid
LEFT JOIN [params] p ON up.param_id = p.id AND (p.name_id = 1 OR p.name_id = 2)
ORDER BY t.id

SQL SELECT statement with users, roles and rights

Lets say that I have tables:
Users
Users_in_Roles
Roles
Rights_in_Roles
Rights
Keys are standard( UserFk, RoleFk, RightFk)
The question is: how to get all users that are in role with right X (id = 100)
I Have no idea how to touch this problem. Please help and sorry for my english.
SELECT [dbo].[System_Users].[Id]
,[UserName]
,[FirstName]
,[LastName]
,[Email]
,RoleFk
,[dbo].[System_Roles].Name
FROM [dbo].[System_Users]
INNER JOIN [dbo].[System_Roles_System_Users]
ON [dbo].[System_Roles_System_Users].UserFk = [dbo].[System_Users].Id
INNER JOIN [dbo].[System_Roles]
ON [dbo].[System_Roles].Id = [dbo].[System_Roles_System_Users].RoleFk
WHERE ?
I tryied sth like that, could you tell me what iw wrong?
SELECT
DISTINCT System_Users.Id,
System_Users.FullName
FROM System_Users
INNER JOIN Dict_Rights_System_Users
ON System_Users.Id = Dict_Rights_System_Users.UserFk
INNER JOIN System_Roles_System_Users
ON System_Roles_System_Users.UserFk = System_Users.Id
WHERE
RightFk = 136
OR
136 IN (SELECT Dict_Rights_System_Roles.RightFk FROM Dict_Rights_System_Roles WHERE
Dict_Rights_System_Roles.RoleFk = System_Roles_System_Users.RoleFk)
ORDER BY System_Users.FullName ASC
You will need to JOIN the tables on the key relationships. The basic structure will be:
select u.Id,
u.UserName,
u.FirstName,
u.LastName,
u.Email,
r.RoleFk,
r.Name RoleName,
rt.Name RightName
from users u
inner join users_in_roles ur
on u.id = ur.userfk
inner join roles r
on ur.rolefk = r.id
inner join rights_in_roles rr
on r.rolefk = rr.rolefk
inner join rights rt
on rr.rightfk = rt.id
where rt.id = 100
If you need help learning JOIN syntax here is a great reference:
A Visual Explanation of SQL Joins
You can try with this:
SELECT *
FROM Users u
WHERE EXISTS (
SELECT ur.RoleFk
FROM Users_in_Roles ur
WHERE u.UserPk = ur.UserFk
AND EXISTS
(
SELECT 1
FROM Rights_in_Roles rr
WHERE rr.RoleFk = ur.RoleFk
AND rr.RightFk = 100
)
)
OR EXISTS (
SELECT 1
FROM Users_Rights uri
WHERE u.UserPk = uri.UserFk
AND uri.RightFk = 100
)
Note that the above query doesn't return RoleFk and Name for the role.
Another approach would be:
SELECT u.Id
,u.UserName
,u.FirstName
,u.LastName
,u.Email
,rr.RoleFk
,r.Name
FROM Users u
-- get users that are in role that has right
LEFT JOIN
Users_in_Roles ur ON
ur.UserFk = u.UserPk
LEFT JOIN
Rights_in_Roles rr ON
rr.RoleFk = ur.RoleFk
AND rr.RightFk = 100
LEFT JOIN
Rights r ON
r.RolePk = rr.RoleFk
-- get users that have a right granted to them directly
LEFT JOIN
Users_Rights uri ON
u.UserPk = uri.UserFk
AND uri.RightFk = 100
WHERE rr.RoleFk IS NOT NULL OR uri.UserFk IS NOT NULL