Selecting a user's friend's events - sql

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

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;

select a column from another table mulipletimes problem

User
USER_ID USERNAME
1 -
2 Chris
3 Dave
4 Vlad
Issue
Creator RESOLVER VERIFIER
2 3 4
2 3 1
3 1 1
expected output:
Creator RESOLVER VERIFIER
Chris Dave Vlad
Chris Dave -
Dave - -
current code I have:
SELECT creatorid.username, resolverid.username, verifierid.username
FROM issue
JOIN user creatorid ON issue.creator = creatorid.user_id
JOIN user resolverid ON issue.resolver = resolverid.user_id
JOIN user verifierid ON issue.verifier = verifierid.user_id
do i have to join the table 3 times to get the corresponding username of the user_id in issue table or is there is a simpler way of doing this? Asking as this is a simplified version of the tables, the User and Issue table contains a lot of other columns. Thanks
Because of the join, you will see each issue three times which is not what you want. You could use three scalar subqueries to get around that:
select i.id,
(select username from users u1 where u1.user_id = i.creator) as creator,
(select username from users u2 where u2.user_id = i.resolver) as resolver,
(select username from users u3 where u3.user_id = i.verifier) as verifier
from issue i;
This isn't going to be fast though.
Another option is to aggregate all user_id / username pairs into a JSON object, then use that in a sub-query:
select i.id, -- other columns from the issue table
u.names ->> i.creator::text as creator,
u.names ->> i.resolver::text as resolver,
u.names ->> i.verifier::text as verifier
from issue i
join lateral (
select jsonb_object_agg(user_id, username) as names
from users u
where u.user_id in (i.creator, i.resolver, i.verifier)
) u on true;
The traditional way to do this is:
select i.*, uc.username, ur.username, uv.username
from issue i left join
users uc
on uc.user_id = i.creator left join
users ur
on ur.user_id = i.resolver left join
users uv
on uv.user_id = i.verifier;

Retrieving data information from another table Left Join SQL

User A liked User C Post
Table Users:
id_user name
1 A
2 B
3 C
Table Posts:
id_post post user_post
15 hi 2
19 how are you 3
23 hello 2
Table likes:
id_like id_liker liked_post_id liked_user_id
45 1 19 3
From table likes I show results
User 1 liked post 19 that belongs to user 3
SELECT liked_user_id,_liker,liked_post_id
FROM likes
WHERE liked_user_id = 3
How do I show the next
User A liked User C Post which is "How are you"
I tried but I get an error:
SELECT name
FROM users as u
LEFT JOIN
(SELECT id_post, post, user_post
FROM posts as p
LEFT JOIN
(SELECT liked_user_id, id_liker, liked_post_id
FROM likes
WHERE liked_user_id = 3
) AS b ON u.id_post = b.liked_post_id
) AS c ON u.id_user = c.user_post
SELECT u.`name`, v.`name`, p.post
FROM likes
LEFT JOIN Users as u on likes.id_liker=u.id_user
LEFT JOIN Users as v on likes.liked_user_id=v.id_user
LEFT JOIN Posts as p on likes.liked_post_id=p.id_post
WHERE likes.liked_user_id=3
SELECT liker.name AS liker_name
,liked.name AS liked_name
,p.post
FROM likes AS l
LEFT JOIN Users AS liker ON liker.id_user = l.id_liker
LEFT JOIN Users AS liked ON liked.id_user = l.liked_user_id
LEFT JOIN Posts AS p ON p.id_post = l.liked_post_id
AND l.liked_user_id = p.user_post
WHERE l.liked_user_id = 3

sql: many to many relationship join

I'm very new to SQL so if there are multiple possibilities I'd like to see them all (and hear which possibilities are better than others). I'm using sqlite3.
I have the following 3 tables: user, channel, subscriptions
user:
user_id name
1 Johnny
2 Stacy
3 Allana
channel:
channel_id channel_name
1 ESPN
2 Disney
subscriptions:
user_id channel_id
1 1
2 2
3 1
3 2
What SQL command do I need to perform to get the following table? I basically want to see who is subscribed to which channels by names (so exactly what's laid out in the subscriptions table but mapping numbers to names based on the other tables).
user_id channel_id
Johnny ESPN
Stacy Disney
Allana ESPN
Allana Disney
I've tried the following but I'm getting nothing in the return statement:
select user.name, channel.channel_name from user, channel, subs where user.user_id == subs.user_id and channel.channel_id == subs.channel_id
Try this out and let me know in case you face any difficulty.
select a.name,c.channel_name
from
user a
left join
subscriptions b
on a.user_id = b.user_id
left join
channel c
on b.channel_id = c.channel_id;
or (in the format u asked in comments)
select u.name,c.channel_name
from
user u
left join
subscriptions s
on u.user_id = s.user_id
left join
channel c
on s.channel_id = c.channel_id;
Haven't tested it but try this:
select
u.name
,c.channel
from
user_id u
inner join subscriptions s
on u.user_id=s.user_id
inner join channel c
on s.channel_id=c.channel_id