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

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

Related

How both asterisked lines are correct given the SQL statement

A new social network site has the following data tables:
Table users:
id
name
sex
1
Ann
null
2
Steve
m
3
Mary
f
4
Brenda
f
Table friends:
user1
user2
1
2
1
3
2
3
Select data that will be returned by the following SQL query:
SELECT users.name,
COUNT(*) as count
FROM users LEFT JOIN
friends ON users.id = friends.user1 OR users.id = friends.user2
WHERE users.sex = 'f'
GROUP BY users.id,
users.name;
Output:
name
count
Ann
1
Ann
2
Steve
1
Steve
2
Mary
1
Mary
2 **
Brenda
0
Brenda
1 **
The asterisked sections are the correct answers, but I don't quite understand why (Brenda, 1) would be an answer here when (Mary, 2) is also a correct answer.
This is a trap question. The query looks like your are selecting all female users (sex = 'f') and count their friendships. For this a left outer join on the friends table is applied, so we keep all female users, no matter whether they have friendships or not.
But then the query uses COUNT(*), which counts the joined rows. That is 2 for Mary and 1 for Brenda. If we wanted to count friendships, we'd have to count a column of the friends table, e.g. COUNT(friends.user1). Thus the outer joined rows having these columns set to null would be omitted from the count, and we'd get 2 for Mary and 0 for Brenda.

How to find the degree of connection in a social network using recursion

Imagine, you are looking at a social network graph of millions of users. Imagine Facebook users who are in different Facebook Groups. Let me give the following example:
We start with Jeff. Jeff has a degree of connection with himself of 0.
Rohit is in the same Facebook group as Jeff, so his degree of connection with Jeff is 1.
Linda is in a facebook group with Rohit, but not in one with Jeff. Her degree connection with Jeff is, therefore 2.
This same phenomenon goes on and on. Now we want to create a query in SQL that can find all users in the user table that have a degree of connection with Jeff of 3 or less. We have the following 2 tables:
user
name
person_id
Jeff
1
Rohit
2
Linda
3
Sid
4
Jin
5
group_in
group_id
person_id
1
1
1
2
2
2
2
3
3
3
3
4
4
4
4
5
What query could find and return all the person_ids and degrees_of_connection for all users with a degrees_of_connection <= 3 with Jeff using just these two tables? The output should show that Jeff, Rohit, Linda, and Sid are all within 3 degrees of connectivity. Whereas Jin would not be included in the results as he is 4 degrees of connection away
You may try the following which uses a recursive cte to find the degree of connection between users. The final projection uses joins to retrieve the respective user names.
WITH user_connections(person_id_1,person_id_2,group_id,no_con) AS (
SELECT
p1.person_id,
p2.person_id ,
p2.group_id ,
case when p2.person_id is null then 0 else 1 end as no_con
from group_in p1
left join group_in p2 on p1.group_id = p2.group_id and p1.person_id < p2.person_id
UNION ALL
SELECT
p1.person_id_1,
p3.person_id,
p3.group_id ,
1+no_con
from user_connections p1
inner join group_in p2 on (
p2.group_id <> p1.group_id and
p2.person_id = p1.person_id_2 and
p1.person_id_2 is not null)
inner join group_in p3 on p3.group_id = p2.group_id and
p3.person_id <> p2.person_id
where no_con < 3
)
SELECT
con_name.person_id,
con_name.name,
uc.no_con as degrees_of_connection
FROM
users u
INNER JOIN user_connections uc ON u.person_id = uc.person_id_1
INNER JOIN users con_name on con_name.person_id = uc.person_id_2
WHERE u.name = 'Jeff';
person_id
name
degrees_of_connection
2
Rohit
1
3
Linda
2
4
Sid
3
Working Demo Fiddle
Let me know if this works for you.

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

Is it possible to get all the parent of a particular role in SQL?

I have a hierarchial (parent-child) role based structure to be used for authorization. I have a simple schema, which stores roles along with the id of their parent. Now I am given a role_id, from which I want to get all the parents of that role.
For example, I have a table like this:
ROLE_ID ROLENAME IS_PARENT PARENT_ROLE_ID
1 1 ABC CORP Y NULL
2 2 ABC EC Y 1
3 3 ABC WC Y 1
4 4 ABC NY Y 2
5 5 ABC OH Y 2
6 6 NY ORTH N 4
7 7 NY CARD N 4
8 8 OH ORTH N 5
9 9 OH CARD N 5
Now, when I am provided with a ROLE_ID of 8, the query should return me:
ROLE_ID
1
2
5
8
Since OH ORTH is a child of ABC OH. ABC OH is a child of ABC EC. ABC EC is a child of ABC CORP, I should get 1,5,2 and 1.
In the above example, there are only 4 levels. But, in actual situation, there might be many levels.
I tried googling solution to this problem and stumbled up here. But this is particular to Oracle, and it gives me syntax error when executing queries on Microsoft SQL Server.
Is this possible? I am using Microsoft SQL server on Microsoft Windows Azure.
I have limited knowledge of SQL. Please help
Yes it's possible. You can use recursive CTE for it.
http://msdn.microsoft.com/en-us/library/ms186243(v=sql.105).aspx
;WITH RCTE AS
(
SELECT ROLE_ID, PARENT_ROLE_ID FROM Table1
WHERE ROLE_ID = 8
UNION ALL
SELECT t.ROLE_ID, t.PARENT_ROLE_ID FROM RCTE r
INNER JOIN Table1 t on r.PARENT_ROLE_ID = t.ROLE_ID
)
SELECT * FROM RCTE
SQLFiddle DEMO

linked tables in firebird, discard records that have a specific value in a one to many linked table

I have two tables in a firebird 1.5 database, the tables are client and notes, in the notes table there can be multiple records for each corresponding record in Client table, and sometimes none.
The tables are structured like
Client
Client_id name
-----------------
1 Sam
2 Lee
3 Steve
4 Linda
5 Sue
6 Jill
7 Jack
Notes
Notes_id client_id Note
------------------------------
1 1 New
2 1 do not send
3 2 old
4 2 likes
5 4 do not send
6 5 new
7 5 Cats and Dogs
8 5 drives
I would like to run a select statement that would only return records from the Client table where there is no note named ‘do not send’ linked to the client in the notes table. So with the above examples the select statement would only return the following records from the client table.
Client_id name
-----------------
2 Lee
3 Steve
5 Sue
6 Jill
7 Jack
Is this possible? Any assistance with this would be appreciated.
Regards Alan
Below are three queries that will do the task:
SELECT
c.*
FROM
client c
WHERE
NOT EXISTS(SELECT * FROM notes n WHERE n.client_id = c.client_id
AND n.note = 'do not send')
or
SELECT
c.*, n.client_id
FROM
client.c LEFT JOIN
(SELECT client_id FROM notes WHERE note = 'do not send') n
ON c.client_id = n.client_id
WHERE
n.client_id IS NULL
or
SELECT
c.*
FROM
client c
WHERE
NOT c.client_id IN (SELECT client_id FROM notes n
WHERE n.note = 'do not send')