Twitter style following-follower table in SQL-2 - sql

Addition to this Twitter style following-follower table in SQL
In the upper example I was able to return the query for "if userB is following the other users who follows him"
I need a simpler thing now. I tried to modify the original code without any luck. I simply need "if userB is following or not any of the users , regardless if they follow him. Currently it returns null for people who dont follow that particular user.
This is the sample table for users
id user_id
1 userA
2 userB
3 userC
4 userD
5 userE
This is the sample table for follows
id user_id follower_id
1 userA userB
2 userD userB
I like to return a result that includes this follower/following state. For example for userB (he follows A and D but not C and E:
id followedBy areWeFollowing
1 userA 1
2 userB 0
3 userC 0
4 userD 1
5 userE 0
Thanks for your help!
arda

you can even take a count also from second table for this situation -
select id,user_id, ( select count(*)
from follows
where follows.user_id = users.user_id
and follows.follower_id = 'userB') as areWeFollowing
from users

Related

OrderBy and sort with 2 tables with doctrine, SQL

I have 2 tables:
User:
id
lastname
role_id
1
UserA
2
2
UserB
1
3
UserD
1
4
UserC
2
Role:
id
name
1
ROLE_B
2
ROLE_A
I would like to order and sort the users with ROLE_B first and alphabeticaly then the rest alphabeticaly, the result should be like this:
id
lastname
role_id
2
UserB
1
3
UserD
1
1
UserA
2
4
UserC
2
I tried with
$qb = $this->createQueryBuilder('user')
->addSelect('roles')
->addSelect('(CASE WHEN roles.name = :firstRole THEN 1 ELSE 0 END) AS HIDDEN orderByRole')
->leftJoin('user.roles', 'roles')
->setParameters(
[
'firstRole' => EnumRole::ROLE_B
]
)
->addOrderBy('orderByRole', 'ASC')
->addOrderBy('user.lastname', 'ASC')
;
But it always orders alphabeticaly by lastname only
If someone know how to do that with doctrine or in SQL, thanks

How to get unique id's data among the same score

The records in the table likes:
user score label
----------------------------------------------
userA 2 apple
userA 2 banana
userB 5 cat
userB 5 dog
For different rows, if the user and score are same, it just need to get the unique user and score, and any label is fine.
The expected query result from above is example can be any one as below:
user score label
----------------------------------------------
userA 2 apple
userB 5 cat
or
user score label
----------------------------------------------
userA 2 banana
userB 5 cat
or
user score label
----------------------------------------------
userA 2 apple
userB 5 dog
or
user score label
----------------------------------------------
userA 2 banana
userB 5 dog
if any label is fine, I think the easiest way is to use an aggregation function like min or max --
SELECT user, score, max(label) as label
FROM table
GROUP BY user, score
you can use window function:
select * from
(
select * , row_number() over (partition by user,score order by label) rn
from tablename
) t
where t.rn = 1;

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;

Get list of user who are involved in conversation

My "users" table is like this
id name
1 UserA
2 UserB
3 UserC
4 UserD
And my "chats" table is like this
id text sentBy sentTo created
1 Hi UserB 1 2 2019-01-11
2 Hi 2 1 2019-01-12
3 Hi UserB 3 2 2019-01-13
4 Hello UserC 2 3 2019-01-14
5 Hello 3 2 2019-01-15
6 What u do 2 1 2019-01-16
7 Nothing 1 2 2019-01-17
8 Okay 2 1 2019-01-18
8 Hi UserA 3 1 2019-01-19
I want to show user list who is involved in a conversation with logged in user based on the last msg.
Like if UserA logged in the system then the list should be like
userId userName text created
3 UserC Hi UserA 2019-01-19
2 UserB Okay 2019-01-19
I tried by using a join query and group by but not succeed.
I am using PostgreSQL with koa js.
You may use DISTINCT ON to filter out all apart from the most recent record for each involved in the conversation.
SELECT DISTINCT ON( involved) involved AS userid,
u.NAME AS username,
text,
created
FROM (SELECT c.*,
CASE sentby
WHEN 1 THEN sentto
ELSE sentby
END AS involved
FROM chats c
WHERE c.sentby = 1
OR c.sentto = 1) s
JOIN users u
ON s.involved = u.id
ORDER BY involved,
created DESC
Demo
If you want a generic case, you may convert this to a SQL type Postgres function and pass userid as an argument and use it in place of 1.
To get a complete list of users involved in the last conversation of the $current_user, with the last message (sent or received) and its date (created):
WITH u1 AS (SELECT id FROM users WHERE name = $current_user)
SELECT DISTINCT ON (userId) *
FROM (
SELECT u.id AS userId, u.name AS userName, c.text, c.created -- received
FROM u1
JOIN chats c ON c.sentBy = u1.id
JOIN users u ON u.id = c.sentTo
UNION ALL
SELECT u.id, u.name, c.text, c.created -- sent
FROM u1
JOIN chats c ON c.sentTo = u1.id
JOIN users u ON u.id = c.sentBy
) sub
ORDER BY userId, created DESC;
I separated into two UNIONed SELECTs, to make the most of two separate indexes on chats - one with leading sentTo, one with leading sentBy. Just updated a closely related answer yesterday:
Finding all rows with unique combination of two columns
About DISTINCT ON:
Select first row in each GROUP BY group?
Might be optimized in various ways, depending on undisclosed information.

SQL Select Where

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