SQL Select Where - sql

i have a table like this
UserFriends
Id UserId RequestId Status
1 1 2 1
2 1 3 1
3 1 4 0
4 3 2 1
5 3 4 1
basically the structure is if status is 0 request not accepted else 1 accepted and they are friends
i am trying to do get user 2 friends how can i do ?
IMPORTANT EDIT:
i am trying to get user 3's friends. you know if user 1 added user 3 they are friends and user 3 added 2 and 4 they friends too (user 3 friends must return 1, 2 and 4 this is basic explanation)

If I read correctly, a friendship is characterized by either a user inviting another user or by that user being invited by other users, and in both cases the request was accepted. If so, then the following UNION query should give the expected results:
SELECT RequestId
FROM UserFriends
WHERE UserId = 3 AND Status = 1
UNION
SELECT UserId
FROM UserFriends
WHERE RequestId = 3 AND Status = 1
I use a UNION here because a given user could appear as a friend more than once if a pair of users invited each other, or if an invitation were sent more than once. I am assuming that you don't want to report the same user as a friend more than once.
Output:
Demo here:
Rextester

Related

Query to fetch user names according to a condition from another table (SQL)

I have two tables:
user
id
full_name
is_admin
is_active
1
Alan
0
1
2
Carl
0
1
3
Any
0
1
4
Jane
0
1
5
Marry
0
1
6
Pedri
0
1
7
admin
1
1
8
Mota
0
0
approver
id
subordinate_id
leader_id
main_leader_id
is_active
1
1
2
3
0
2
4
5
6
1
3
1
2
4
0
(subordinate_id, leader_id and main_leader_id are foreign keys that correspond to the id column of the user table)
I would like to perform a query that brings all user names that are not admin (user table is_admin=0) and that are active (user table is_active=1), and that if they have the id in the subordinate_id column in the approver table that only brings the name of that user that has the is_active of the approver table = 0.
That is, I would like to bring users that if they have any record as subordinate_id that only bring me those that are not active in the approver table.
I tried to get the data in the following way:
SELECT
full_name
FROM user AS U
LEFT JOIN approver AS A
ON U.id = A.subordinate_id
WHERE
A.id is null
AND
U.is_admin = 0
AND
U.is_active = 1
But with this query i only get the user name that not has a register in the approver table,
and in my case i want to get the user that have a register in the approver table as subordinate_id, but not if the register have the column 'is_active' equal to 1.
In my final result I could get something like this:
Alan
carl
any
marry
Pedri
In order to make this working, you should split the conditions in the WHERE clause into:
"user" conditions: is_admin = 0 AND is_active = 1
"approver" conditions: is not a subordinate OR is_active = 0
These two groups of conditions have to be set in AND.
SELECT DISTINCT user_.id, user_.full_name
FROM user_
LEFT JOIN approver
ON user_.id = approver.subordinate_id
WHERE (user_.is_admin = 0 AND user_.is_active = 1)
AND (approver.id IS NULL OR approver.is_active = 0)
Check the demo here.
Note: the DISTINCT keyword is necessary because the JOIN operation is made between two tables having cardinality 1:n.

Counting association between records

I have a dataset of users who have liked each other. The data looks like
User HasLiked
User 1 User 3
User 1 User 4
User 1 User 5
User 2 User 3
User 3 User 1
User 4 User 1
User 4 User 5
User 5 User 3
User 5 User 4
I can get count of liked users for any given user using
select user, count(*) as liked_count
from users
group by user;
which gives me
User liked_count
User 1 3
User 2 1
User 3 1
User 4 2
User 5 2
However I can't figure out how to count the number of times a user is liked back by someone they have liked. e.g what I want is:
User liked_count liked_back_count
User 1 2 2
User 2 1 0
User 3 1 1
User 4 2 2
User 5 2 1
Any ideas how to do this using sql? FYI, The number of distinct users is around 100K.
You can use a left join to determine if the "inverse" record appears. And then aggregate:
select u.user, count(*) as liked_count,
count(*) filter (where u2.user is not null) as liked_back_count
from users u left join
users u2
on u2.user = u.hasliked and
u2.hasliked = u.user
group by u.user;

Small Following system. How to select two different values from a column

I'm working on a small project similar to, let's say, Twitter, where somebody can follow you and you can follow others.
I'm trying to figure out how to show which people a person is following.
An example:
login
ID username
1 jhon
2 bob
3 james
4 kate
followers (sta stands for stalker and fol for following)
ID idsta idfol
1 1 3
2 1 4
3 2 1
4 3 4
5 3 1
6 3 2
7 4 2
I managed to write a some-what working query, but for the "fol" table it shows just one person and not every person that is following.
SELECT sta, fol
FROM (SELECT login.username
FROM login, followers
WHERE login.id = 3 and login.id=followers.idsta) AS sta,
(SELECT login.username
FROM login,followers
WHERE login.id = 2 and login.id=followers.idfol) AS fol
And I would like to show me something like :
User Following
james kate
james bob
james jhon
Hope you guys can understand my problem. Thanks for your time.
Looks like you want to join followers to login to get the followers for a login and join login again to get their names.
SELECT l1.username "User",
l2.username "Following"
FROM login l1
INNER JOIN followers f
ON f.idsta = l1.id
INNER JOIN login l2
ON l2.id = f.idfol
WHERE l1.id = 3;
SQL Fiddle

optimize sql query

I've a user table in my application.
Id Name ParentId
1 User1 0
2 User2 1
3 User3 1
4 User4 2
5 User5 2
The users have a relationship like grandparent->parent->child. to fetch the users related to a grand parent I'm using the following query
select * from user where ParentId=1 or ParentId in(select id from user where ParentId=1)
also these user have multiple roles in my role table and for fetching the count of rules a user having, I'm using select count(*) from group where userId=1.
Id Role UserId
1 Role 1 1
2 Role 2 1
3 Role 3 2
4 Role 4 2
5 Role 5 3
I need to fetch these both data in a single query .I'm not good with SQL and I know my first query is not perfect . How can I achieve this.
Your query is just need to be joined with your roles table.
SELECT u.id, count(r.id) no_of_roles
FROM user u left join roles r
on u.id = r.userid
WHERE u.ParentId=1
OR u.ParentId IN
(SELECT id FROM t WHERE ParentId=1
)
group by u.id;

Aggregate list of users and values into a table with list of users and counts of values

I have a table of users with three columns.
Username Accepted Rejected
User 1 1 NULL
User 1 1 NULL
User 1 NULL 1
User 2 1 1
User 3 1 NULL
User 3 1 NULL
User 2 NULL 1
User 3 NULL NULL
User 2 NULL NULL
I'd like to show a list of all the users with counts of Accepted/Rejected columns like so:
Username Accepted Rejected
User 1 2 1
User 2 1 2
User 3 2 NULL
What is the best way to do it?
If Accepted and Rejected can contain 1, 0 and null only use sum because sum will return null if all values supplied are null:
select UserName,
sum(Accepted) Accepted,
sum(Rejected) Rejected
from ATable
group by UserName
Count will return zero in Rejected column of user3.
SELECT
u.username,
CASE
WHEN COUNT(u.accepted) = 0 THEN NULL
ELSE
COUNT(u.accepted)
END AS Accepted,
CASE
WHEN COUNT(u.rejected) = 0 THEN NULL
ELSE
COUNT(u.rejected)
END AS Rejected
FROM
usr1 u
GROUP BY u.username