SQL JOIN Returning no values - sql

I am working with 3 tables with the following Names and columns:
*Table 1*
**Users**
UserID UserName UserTypeNumber
1 John 1N
2 Mary 1N
3 Doe 1N
4 Sullivan 2N
5 Sally 1N
**Key = UserID**
*Table 2*
**MobileUsers**
Userid MobileAccess
1 Yes
2 Yes
3 Yes
4 Yes
5 No
**Key = UserID**
*Table 3*
**PanCards**
UserID CARD_NUMBER
3 2222
4 3333
5 1111
Key = UserID
Explanation:
Every user is available in both Users and MobileUsers table
However, not all users are present in PanCards table. This is
because only users that have been assigned a Card appears in the
PanCards table. In this case Doe with UserID=3 and Sullivan with UserID=4 have a card, hence they appear in PanCards table
Problem:
What I want to achieve is to filter out the users from
MobileUsers table that have MobileAccess equivalent to Yes and thier UserTypeNumber equivalent to 1N in the Users table but are not present in the PanCards table.
What I have so far is the below SQL Query:
SELECT MobileUsers.Userid, MobileUsers.MobileAccess
FROM MobileUsers
INNER JOIN Users
ON MobileUsers.Userid = Users.UserID
INNER JOIN PanCards
ON Users.UserID = PanCards.UserID
WHERE MobileUsers.MobileAccess = 'Yes'
AND
Users.UserTypeID = '1N'
AND
MobileUsers.Userid NOT IN
(SELECT PanCards.UserID FROM PanCards)
Result is an Empty table
Userid MobileAccess
However what i want is to have the below result returned:
Userid MobileAccess
1 Yes
2 Yes
How do i fix this and get the correct results please ?

If you want to use JOIN, then use a LEFT JOIN for PanCards and check for no matches:
SELECT mu.*
FROM MobileUsers mu JOIN
Users u
ON mu.Userid = u.UserID LEFT JOIN
PanCards pc
ON pc.UserID = mu.UserID
WHERE mu.MobileAccess = 'Yes' AND
u.UserTypeID = '1N' AND
pc.UserID IS NULL;
I think your query would work without the join to PanCards.

WITH NotPan -- First get users that are not in the PanCards table
AS
(
select * from Users as u
where u.userid not in (select userid from PanCards)
)
-- Easy from here
select * from NotPan as n
inner join mobileUsers m on m.userid = n.userid
inner join Users as u on n.userid = u.userid
WHERE m.MobileAccess = 'Yes' and u.UserTypeNumber = '1N'

Related

Database join where

Database
Users
id
lastname
firstname
1
Sardor
Sattarov
2
Nurmuhammad
To’xtayev
3
Jasur
Sattarov
Group_items
id
student_id
group_id
1
2
55
2
1
55
3
2
11
Return
example 1
condition
users.id == group_items.student_id do not publish a table that satisfies this desire group_items.id == 55
id
lastname
firstname
3
Jasur
Sattarov
example 2
condition
users.id == group_items.student_id do not publish a table that satisfies this desire group_items.id == 11
id
lastname
firstname
1
Sardor
Sattarov
3
Jasur
Sattarov
Looks like you want OR instead of AND.
SELECT
*
FROM
users u
LEFT JOIN group_items gi ON u.id = gi.student_id
WHERE
gi.student_id IS NULL
OR gi.group_id <> 5
Studends without a group plus studends in all groups but 5.
Please try this,
Example 1:
SELECT
U.ID,U.LASTNAME,U.FIRSTNAME
FROM
USERS U
LEFT JOIN
GROUP_ITEMS G
ON U.ID=G.STUDENT_ID
WHERE G.GROUP_ID <>55
Example 2:
SELECT
U.ID,U.LASTNAME,U.FIRSTNAME
FROM
USERS U
LEFT JOIN
GROUP_ITEMS G
ON U.ID=G.STUDENT_ID
WHERE G.GROUP_ID <>11
You can use join statements in SQL
For Example
for return 1:
SELECT * FROM users u left join group_items gi on gi.student_id = u.id
this query will return all students with their group_id
for filter by group you can use where statement.
SELECT * FROM users u left join group_items gi on gi.student_id = u.id where gi.group_id<>11

Dynamically select the table to join in Postgres with case statements

My notifications table has a column called action_id and trigger_type. I want to INNER JOIN action_id with another table (Like users or posts) depending on the trigger_type. I wrote the following query but it throws an error.
Table structure
users
display_name
username
id
John
Doe
1
Larry
Doe
2
posts
post_title
post_body
id
user_id
Hello
Hello world
1
2
comments
comment_text
post_id
id
user_id
Hello
1
1
1
notifications
read
trigger_id
id
target_id
action_id
trigger_type
false
1
1
2
1
0
false
1
2
2
1
1
trigger_type = 0 means its a like 1 means its a comment
SELECT notifications.*, users.display_name, users.username, users.profile_pic, posts.title
FROM notifications
INNER JOIN users ON users.id = notifications.trigger_id
(
CASE notifications.trigger_type
WHEN 0 THEN INNER JOIN users ON users.id = notifications.action_id
WHEN 1 THEN INNER JOIN posts ON posts.id = notifications.trigger_id
)
You cannot conditionally join like that. Instead, use left join like this:
SELECT n.*,
-- whatever columns you want from the trigger user go here
un.display_name, un.username, un.profile_pic, p.title
FROM notifications n JOIN
users u
ON u.id = n.trigger_id LEFT JOIN
users un
ON un.id = n.action_id AND n.trigger_type = 0 LEFT JOIN
posts p
ON p.id = n.action_id AND n.trigger_type = 1;

Where clause in sql query remove also null values

I have these tables:
'Users'
id email name last_access
1 luca#gmail.com Luca Pluto 2012-10-05 17:21:22.0
2 pippo#gmail.com Irene Pippo 2012-10-05 17:22:25.0
'Nets_permissions'
user_id network_id perm
1 1234 3
1 1235 1
2 1235 3
I've written this query:
SELECT u.id, u.name, n.perm
FROM users as u LEFT OUTER JOIN nets_permissions as n
ON u.id = n.user_id
WHERE n.network_id=1234 AND n.perm <> 3
because I want users that already have a permission for network_id (1234) , but also users that don't have a permission for the network_id. In other words I would have this result query:
2 null null
because the user Luca Pluto with id=1, for the net 1234, have perm=3 so I want left out. Instead, the user Irene Pippo with id=2 doesn't have any permission on the 1234 net. So it's row must have net_id and perm set to null.
My query result is empty. I don't know why. Without the clause n.perm <> 3 seems to work well, but after also the null value are left out, not only the rws with perm=3.
I've also tried in this way:
SELECT u.id, u.name, n.perm FROM users as u LEFT OUTER JOIN
(select * from nets_permissions WHERE network_id=1234) as n on u.id = n.user_id
WHERE n.perm <> 3
but it doesn't work. without the WHERE clause all works. After no. The result query is empty.
How I can resolve this problem? I need that the perm column is a value or null, I can't remove this column.
The right solution is:
SELECT u.id, u.name, n.perm FROM users as u LEFT OUTER JOIN
(select * from nets_permissions WHERE network_id=1234) as n on u.id = n.user_id
WHERE (n.perm <> 3 or n.perm is NULL)
Here Working with NULL Values there is a expanation of the treatment of NULL values in MySQL
Thank you all for your help!
Many SQL dialect use a special trinary logic with NULL the third possible value additional to true and false.
Anything compared to NULL results to NULL which in turn is handled as false.
So x = null will result in false for all x, just as x != null
If you want to include NULL values in the result you have to add special handling for that (Oracle syntax):
SELECT u.id, u.name, n.perm
FROM users as u LEFT OUTER JOIN nets_permissions as n
ON u.id = n.user_id
WHERE n.network_id=1234
AND (n.perm <> 3 or n.perm is not null)
SELECT u.id, u.name, n.perm
FROM
users as u
LEFT OUTER JOIN
nets_permissions as n ON u.id = n.user_id
WHERE
n.network_id = 1234 and n.perm <> 3
or
n.network_id <> 1234
or
n.network_id is null
I like users that user the "JOIN" syntax. It has additional benefit, aside from making the code easier to read, that people don't realize.
SELECT u.id, u.name, n.perm
FROM users as u LEFT OUTER JOIN nets_permissions as n
ON u.id = n.user_id
AND n.network_id=1234
WHERE COALESCE(n.perm,-1) <> 3

SQL Join to only one record in one to many relationship

I have the following query:
SELECT c.[ClientID]
,u.[AccessId]
FROM [tblClient] c
INNER JOIN [tblUser] u ON u.[Id] = c.[UserId]
This tblUser has multiple ID's for each UserID row.
So it would look like this:
UserID AccessID
1 AD2F0A-965B78414-2B34906F2-0127AA5A
1 ID2F0A9-65B784-142B34906-F20127AA5A
1 UD2F0A9-65B78-4142B34906F-20127AA5A
2 TD2F0A9-65B784142-B34906F-20127AA5A
2 RD2F0A9-65B784142B3-4906-F20127AA5A
3 WD2F0A96-5B784142-B34906F201-27AA5A
3 ZD2F0A96-5B784-142B34-906F2-0127AA5A
3 CD2F0A965-B784142B3-4906F20-127AA5A
Is there a way to only get the top(or 1) AccessId for each UserID? It doesnt matter which AccessID i get, I just want 1 of them.
Thanks
SELECT c.[ClientID], MAX(u.[AccessId])
FROM [tblClient] c
INNER JOIN [tblUser] u
ON u.[Id] = c.[UserId]
GROUP BY c.[ClientID]

Selecting a user's friend's events

I have these information :
Table "Users" =>
**Id** **Name**
1 a
2 b
3 c
4 d
5 e
Table "Friends" =>
**SenderId** **ReceiverId** **State**
1 2 x
2 3 ok
3 1 ok
3 4 ok
5 3 ok
5 4 ok
Table "Events" =>
**SenderId** **receiverId** **text**
1 1 3 ssss
2 3 1 dsadsa
3 2 3 safsdf
4 3 5 fgfdgfd
5 4 3 fgfhgfh
6 5 4 sad sad
My question is that how could I get the events of user's friends in one sql statement using JOINS only .
for example :=>
userId : 1
his friends : 3 (state = ok)
friends events : 1, 2, 3, 4, 5 (events from 1 to 5 have the userId 3 which considered as a friend to user 1 )
ANY HELP .. THANKS ;) !!
You didn't specify a name for the first column in your Events table so I've called it row_ID:
SELECT U1.ID AS user_ID, U1.Name AS user_name,
U2.ID AS friend_user_ID, U2.Name AS friend_user_name,
E1.row_ID, E1.text AS event_text
FROM Users AS U1
INNER JOIN Friends AS F1
ON (
U1.ID = F1.ReceiverId
OR U1.ID = F1.SenderId
)
AND F1.State = 'ok'
INNER JOIN Users AS U2
ON U2.ID = F1.SenderId
INNER JOIN Events AS E1
ON (
U2.ID = E1.ReceiverId
OR U2.ID = E1.senderId
)
WHERE U1.ID = 1;
Your table structure is quite confusing with all those Sender and Receiver ID's, but I think the following query will work.
SELECT * FROM
(SELECT Users.Name, Events.text
FROM Users
LEFT JOIN Friends ON Users.Id = Friends.ReceiverId
LEFT JOIN Events ON Friends.SenderId = Events.SenderId
WHERE Users.Id = 1)
UNION ALL
(SELECT Users.Name, Events.text
FROM Users
LEFT JOIN Friends ON Users.Id = Friends.ReceiverId
LEFT JOIN Events ON Friends.SenderId = Events.ReceiverId
WHERE Users.Id = 1)
You can probably simplify this, but I'm not sure how, considering you want to select events 1-5 because the friend ID can be either the Events.SenderId or the Events.ReceiverId.
I don't know if SQL supports this, but maybe put an OR into the LEFT JOIN clause (?):
SELECT Users.Name, Events.text
FROM Users
LEFT JOIN Friends ON Users.Id = Friends.ReceiverId
LEFT JOIN Events ON (Friends.SenderId = Events.SenderId OR Friends.SenderId = Events.ReceiverId)
WHERE Users.Id = 1
It's pretty easy with a sub-query.
Here's the subquery (find user 1's friends)
SELECT
senderID
FROM
friends
WHERE
receiverID = 1
Here's the main query (find user1's friend's events)
SELECT
primary_key,
senderID,
receiverID,
text
FROM
events
WHERE
senderID IN (subquery) --events where user1's friends were the senders
OR receiverID IN (subquery) --events where user1's friend's were the receivers
Put it all together:
SELECT
*
FROM
events
WHERE
senderID IN (SELECT
senderID
FROM
friends
WHERE
senderID = 1) --events where user1's friends were the senders
OR receiverID IN (SELECT
senderID
FROM
friends
WHERE
receiverID = 1) --events where user1's friend's were the receivers
You might consider replacing the explicit '1' with a variable, so you can run this query for every user.
Good luck