How to find common matches for different column values in SQL - sql

I have the following table "Friends":
The goal is to find out how many users have the exact same list of friends.
In this case, the result would be user_id 1 and user_id 4 since both user 1 and user 4 are friends with "2" and "3".
I think I am on the right track by using the code below:
SELECT * FROM Friends A, Friends B WHERE A.friend_id=B.friend_id AND A.user_id <> B.user_id
However, I am not able to figure out how to finish the query so that it calculates the matching list of friends. Does anyone have any suggestions?

You didn't provide your SQL type.
For MySQL, you can group concat the friends for every user and cross by this value. The default is ",". Then join the same table to compare by the same list of friends.
SELECT t1.friends, t1.friends FROM
(
SELECT user_id,GROUP_CONCAT(friend_id) as friends
FROM friends
GROUP BY friend_id
) as t1
JOIN
(
SELECT user_id,GROUP_CONCAT(friend_id) as friends
FROM friends
GROUP BY friend_id
) as t2
on t1.friends = t2.friends

Related

SQL selecting multiple record by different variable

Ok, so I have a table Assignment:
[UserId]
[GroupId]
[UpdatedBy]
[UpdatedAt]
Also, I have a function for returning users from a specific group:
select UserId
from dbo.GetGroupUsers() ggu
where ggu.GroupId = ?
In Assignment, I want to check all groups that our user is listed and then I want to select ALL users from these groups, without duplicate.
How can I achieve this?
Edit:
Sample output form selecting groupid = 4
for example user "test1" belong to other group where id=2 at the same time and i want selected all users from for example group 2 and 4 (cause in this example test1 said so) without records duplicate
All groups from one UserId (say UserId 10):
select GroupId from Assignment where UserId = 10
Select all users from those groups (without duplicate):
select distinct UserId
from dbo.GetGroupUsers() ggu
where ggu.GroupId in (select GroupId from Assignment where UserId = 10)
I hope this is what you wanted.
An inner self join should get you the IDs of the users you're looking for. Join the result with your user table (which you didn't post) to possibly get other information about these users.
SELECT DISTINCT
a2.userid
FROM assignment a1
INNER JOIN assignment a2
ON a2.groupid = a1.groupid
WHERE a1.userid = ?;
(Replace the ? with the ID of the user, you want to start with.)
Assuming your input is a user id:test1 and assuming that you are just looking at one table (Assignment)
DECLARE #UserId INT = 2
;WITH GROUPS AS
(
SELECT DISTINCT GroupId FROM Assignment WHERE UserId = #UserId
)
SELECT distinct assgn.UserName, gps.GroupId FROM Assignment assgn
INNER JOIN
GROUPS gps ON
assgn.GroupId = gps.GroupId
Please let me know if this helps

Sqlite query all the missing ids

I got two tables in my DB, users and gifts. The user table got id and data, the gifts table got gift_id, user_id and data.
gitst.user_id associated with users.id
How can I get all the user_id from gifts table that not appear in users table?
One way to do it is using the except operator.
select user_id from gifts
except
select id from users
Except gives you the difference of two sets.
Let's say set A = {1,2,3} B={3,4,5,6}.
A-B = {1,2} because 3 exists in both the sets and 1,2 exist in A but not in B
B-A = {4,5,6} 3 is common to both sets and 4,5,6 exist in B but not in A
You can also do
select user_id from gifts
where user_id not in (select id from users)
or
select user_id from gifts g
where not exists (select 1 from users where id = g.user_id)
select user_id from gifts not exists(select id from users)

Check if any children exist

Considering these two tables:
Position(positionid, positiontext, reportstopositionid)
User(userid, positionid)
How can I check if a user has any subordinates in one query?
Is it even possible?
A subordinate:
user (a) with positionid has at least one or more subordinates if there exists any users (b) with the positionid of user (a) as reportstopositionid to users (b) corresponding positionid
This will return users who have subordinates:
SELECT *
FROM User u
WHERE EXISTS (
SELECT 1
FROM Position p
WHERE p.reportstopositionid = u.positionid
)
how about this one?
SELECT DISTINCT a.*
FROM user a
INNER JOIN position b
ON a.userID = b.reportstopositionID
the records returned by this query are those which has matching IDs userid on position table at column reportstopositionID
I think you want to do this with a where clause:
select u.*
from user u
where u.positionId in (select reportstopositionid from position p)
This gets the list of users who match, without duplicates.

Getting two rows "in scope" for a PostgreSQL function call: cross join?

I have a user-defined function similarity() that compares two users and returns a score. Right now, the calling query looks like:
SELECT similarity(user1, user2)
FROM (
SELECT users.id
FROM users AS user1
WHERE users.id = 123
)
CROSS JOIN
(
SELECT users.id
FROM users AS user2
WHERE users.id = 456
);
This feels messy. Is there a better way to set up the two users for the function call?
If there is only one from each table (seems likely that id is a PK) then
SELECT similarity((SELECT a FROM users a WHERE a.id=123),
(SELECT b FROM users b WHERE b.id=456));
Simplified form that does exactly the same:
SELECT similarity(a, b)
FROM users a, users b
WHERE a.id = 123
AND b.id = 456;

SQL - Select all skills

it's been a while since I used SQL so I'm asking sorry if it's too easy.
I have to select all the skills that a user has, so I have three tables.
User (id, name)
Skills (id, name)
User_skills (id_user, id_skill)
If the user1 has 2 skills; for example Hibernate (id 1) and Java (id 2)
and the user2 has 1 skill; Java (id 1)
Passing 1 and 2, I want to retrieve users that have both.
With the IN() function I get all the users that have at least one of the skills, but I want to filter them out!
Thanks to all in advance
If one skill can only be assigned exactly once to a user (i.e. (id_user, id_skill) is the PK for the user_skills table), then the following will do what you want:
SELECT id_user
FROM user_skills
WHERE id_skill IN (1,2)
GROUP BY id_user
HAVING count(*) = 2
Join to the association table user_skills twice, putting the skill ID in the on clause of each join:
select u.*
from user u
join user_skills us1 on us1.id_user = u.id and us1.id_skill = 1
join user_skills us2 on us2.id_user = u.id and us2.id_skill = 2
By using join (and not left join) this query requires the user have both skills
SELECT name FROM user as u
WHERE
EXISTS( SELECT 1 FROM User_skills WHERE id_user=u.id AND id_skill=1 )
AND EXISTS( SELECT 1 FROM User_skills WHERE id_user=u.id AND id_skill=2 )