SQL Query Multiple Conditions - mysql

I have two tables like these.
They represent an interaction of following/followers between two users.
users
---------------------------------------
id | username | <br>
1 | bobby | <br>
2 | jessica | <br>
3 | jonny | <br>
4 | mike | <br>
follows
----------------------------------------
id | userid_1 | userid_2 | <br>
1 | 1 | 2 | <br>
2 | 3 | 4 | <br>
3 | 4 | 1 | <br>
Set my user id to 1 for example, I want a query that returns something like this
-----------------------------------------
username | userid_1 | userid_2 |<br>
jessica | 1 | 2 |<br>
mike | 4 | 1 |<br>
Any help to solve this problem? :)

This is a bit more complicated than it first seems, because you want the name of the other user:
select u.username, f.*
from follows f join
users u
on (u.id = f.userid_1 and f.userid_2 = 1) or
(u.id = f.userid_2 and f.userid_1 = 1)
where 1 in (f.userid_1, f.userid_2);
Actually, the where clause is not needed (it is covered by the on). I think it clarifies the filtering however.

You can JOIN tables in following:
SELECT u.username, f.userid_1, f.userid_2
FROM users u
JOIN follows f
ON u.Id = f.Id

Select username, userid_1, userid_2
from users, follows
where users.id = follows.id

Related

SQL: Get top users that follow same users

I have the table followers that looks like this:
id |follower_id|followee_id|
1 | 1 | 2 |
2 | 1 | 3 |
2 | 1 | 4 |
3 | 2 | 3 |
4 | 2 | 4 |
5 | 3 | 2 |
6 | 4 | 6 |
Where follower is a user_id and followee is the user they follow.
How can I find the users that have the most common followees with let's say user 1?
The results need to be ordered by number of common followees.
For example for the current table the results for user 1 would be:
follower_id|common_followees|
2 | 2 |
3 | 1 |
As you can see 4 does not appear in results since it has no common followees with user 1
I hope I explained the problem right.
Thank You.
This is a self-join and aggregation:
select f.follower_id, count(*) as num_common_followees
from followers f join
followers f1
on f.followees = f1.followees and f1.follower_id = 1
group by f.follower_id;
You can add where f.follower_id <> 1. I like to leave that row in as a validation check.

Get shared contacts for two users from multiple MySQL tables

I have two tables in my MySQL database.
The first one stores a list of users, and the other, stores a list of contacts for each user.
Users table:
+----+----------+--------------+
| id | name | phoneNumber |
+----+----------+--------------+
| 1 | David | 661-618-5436 |
| 2 | Sarah | 818-526-4830 |
| 3 | Suzan | 323-623-3493 |
+----+----------+--------------+
Contacts table:
+----+-----------------+--------+--------------+
| id | belongsToUserId | name | phoneNumber |
+----+-----------------+--------+--------------+
| 1 | 1 | Gerard | +18185329384 |
| 2 | 1 | Austin | +18739283847 |
| 3 | 2 | Jamie | +15655468907 |
| 4 | 2 | Jade | +19893828192 |
| 5 | 3 | Phil | +18786754234 |
| 6 | 3 | Duke | +18765467832 |
| 7 | 3 | Gerard | +18185329384 |
| 8 | 3 | Jade | +19893828192 |
+----+-----------------+--------+--------------+
What I want to do, is create a query that efficiently takes 2 user IDs and returns the common contacts by phoneNumber for these two users.
For example: User IDs 1 & 3 both have Gerard | +18185329384 in their contacts so the query will return only him.
What could be the most efficient query for this kind of task?
Thanks :)
If I understood your question correctly, I think this might be what you're looking for:
SELECT
c1.id,
c1.belongsToUserId,
c1.phoneNumber,
c1.name
FROM
Contacts c1
JOIN
Contacts c2 ON (c1.phoneNumber=c2.phoneNumber AND c2.userId=3)
WHERE
c1.belongsToUserId =1
You want a self-join:
select c1.name, c1.phonenumber
from contacts c1 join
contacts c2
on c1.name = c2.name and c1.phonenumber = c2.phonenumber and
c1.belongsToUserId = 1 and
c2.belongsToUserId = 3;
The following SELECT will give you all contacts who has more than 1 User.
SELECT Contacts.name, Contacts.phoneNumber
FROM Users INNER JOIN Contacts ON (Users.id = Contacts.belongsToUserId)
GROUP BY Contacts.name, Contacts.phoneNumber
HAVING COUNT (*) > 1
Following query will display shared contact along with the UseID who's having common contacts.
If you just want to show details of shared contacts, then you can skip first 2 columns.
select min(belongsToUserId) as User1,
max(belongsToUserId) as User2,
name,
phone Number
from contacts
group by name,phoneNumber
having count(*) > 1;
SELECT
cp.name,
cs.phoneNumber
FROM
Contacts cp
INNER JOIN Contacts cs ON
cp.name = cs.name AND cp.phoneNumber = cs.phoneNumber
AND
cp.belongsToUserId IN ( 1,3 );

replace the id with the username from an other table in a CROSS JOIN in MySQL

This question is regarding this one: Joining multiple tables to get NOT EQUAL values in MySQL
I want to extend the following query:
SELECT
d.dataid,
d.colors,
u.userid,
u.username
FROM
users u
CROSS JOIN
datas d
WHERE
(u.userid , d.dataid) NOT IN (SELECT
c.userid, c.dataid
FROM
collections c)
AND u.userid = 1
For this data sample:
table datas table users table collections
dataid | colors | addedby userid | username collectionid | userid | dataid
-------------------------- ------------------- ------------------------------
1 | blue | 1 1 | Brian 1 | 1 | 1
2 | red | 1 2 | Jason 2 | 2 | 3
3 | green | 2 3 | Marie 3 | 1 | 3
4 | yellow | 3 4 | 3 | 2
These results are expected:
for Brian
dataid | colors | userid | username
-----------------------------------
2 | red | 1 | Brian
4 | yellow | 1 | Marie
for Jason
dataid | colors | userid | username
-----------------------------------
1 | blue | 2 | Brian
2 | red | 2 | Brian
4 | yellow | 2 | Marie
The row "addedby", which inherits the userid from users, has been added.
At the moment my query replaces the userid from users instead of the addedby from datas with the username.
I really need the userid from datas replaced, not the userid from users. :-)
Does anyone have a clue how to solve this?
Thanks in advance!
cheers
Just join users table once again with datas table. And in the output use username from this join.
SELECT
d.dataid,
d.colors,
uo.userid,
uo.username
FROM
users u
CROSS JOIN
datas d
INNER JOIN
users uo
ON d.added_by = uo.id
WHERE
(u.userid , d.dataid) NOT IN (SELECT
c.userid, c.dataid
FROM
collections c)
AND u.userid = 1
And I believe, that you might even write your query in this way
SELECT u.userid, u.username, d.dataid, d.colors
FROM username u
INNER JOIN datas d
ON u.userid = d.addedby
WHERE d.dataid NOT IN (
SELECT dataid
FROM collections
WHERE userid = 1
)

MYSQL - Find records from one table which don't exist in another

I've got the following two SQL tables (in MySQL):
Users
| id | name |
|----|------|
| 1 | Luke |
| 2 | Mark |
| 3 | Lucy |
| 4 | Biff |
User category
| user_id | category_id |
|---------|-------------|
| 1 | 5 |
| 1 | 6 |
| 2 | 5 |
| 2 | 7 |
| 3 | 5 |
I want users that are in User category but not if category id is 6.
In this case Mark and Lucy because Luke is in category 6 too and Biff has no category.
There is a way to do it without subquery and only in one query?
You can group by user_id and eliminate those rows where there is atleast one category_id of 6.
select uc.user_id,u.name
from user_category uc
join users u on uc.user_id = u.id
group by uc.user_id,u.name
having sum(case when category_id = 6 then 1 else 0 end) = 0
Join them and check for difference :
SELECT * FROM users
INNER JOIN user_category ON (user_category.user_id = users.id)
WHERE user_category.category_id <> 6
p.s. using group by is not effective, cuz it says to DB engine to do additional group by operation after gathering data.

Many to many query with 3 tables

I have 3 tables: WAS, USER and connection table WAS_USER. The thing I would like to achieve is to get all the rows from table WAS and if there are many users to the same WAS I would like to have one row for each one.
for example:
WAS:
id | name
1 | 'was1'
2 | 'was2'
USER:
id | name
1 | 'user1'
2 | 'user2'
WAS_USER:
userId | wasId
1 | 1
2 | 1
So after queering I need to get this:
wasrId | userId | wasName | userName
1 | 1 | 'was1' | 'user1'
1 | 2 | 'was1' | 'user2'
1 | 2 | 'was1' | 'user2'
Ordinary join between the 3 tables will give my only rows from WAS, what I need is some kind of left join on 3 tables.
Ok, here is what worked for me:
SELECT *
FROM
(SELECT * FROM WAS W LEFT JOIN WAS_USER WU ON W.id=WU.wasID) TMP LEFT JOIN USER U ON TMP.userId=U.userId
Don't know about the efficiency though...