How can I get the name of friends? - mysql

I have two tables like these:
// users
+----+----------+
| id | name |
+----+----------+
| 1 | John |
| 2 | Peter |
| 3 | Martin |
| 4 | Barman |
| 5 | Jack |
| 6 | Ali |
+----+----------+
// friends
+-----------+---------+
| friend_id | user_id |
+-----------+---------+
| 2 | 1 |
| 5 | 1 |
| 1 | 3 |
| 2 | 3 |
| 5 | 3 |
| 2 | 4 |
| 1 | 5 |
| 4 | 5 |
+-----------+---------+
And this is expected result:
+-----------+---------+
| f_name | u_name |
+-----------+---------+
| Peter | John |
| Jack | John |
| John | Martin |
| Peter | Martin |
| jack | Martin |
| Peter | Barman |
| John | Jack |
| Barman | Jack |
+-----------+---------+
I know, I need to use JOIN clause. But I don't know how should I do that correctly?
SELECT * FROM friends f
INNER JOIN users u
ON f.friend_id = u.id
Do I need another JOIN?
Edited: Can I get them in the same column and remove the duplicates? Like this: (I don't care about the order)
+-----------+
| f_name |
+-----------+
| Peter |
| Jack |
| John |
| Martin |
| Barman |
+-----------+
Actually I want a name list of everybody which exits into friend table (either friend_id column or user_id column)

You can try the following
SELECT u1.name AS f_name, u2.name AS u_name
FROM friends
INNER JOIN users u1 ON friends.friend_id = u1.id
INNER JOIN users u2 ON friends.user_id = u2.id
To get the names of all users used in friends you can use the following:
SELECT DISTINCT name
FROM users WHERE users.id IN (
SELECT friend_id FROM friends
UNION
SELECT user_id FROM friends
)

Related

How can I get the name of voter from the user's table?

Here is my current database structure:
// users
+----+--------+
| id | name |
+----+--------+
| 1 | Jack |
| 2 | Peter |
| 3 | John |
| 4 | Barman |
| 5 | Ali |
+----+--------+
// vote
+----------+---------------+
| voter_id | owner_post_id |
+----------+---------------+
| 2 | 3 |
| 4 | 2 |
| 1 | 1 | -- people can vote to its own posts
| 5 | 2 |
| 2 | 2 |
| 3 | 2 |
+----------+---------------+
And this is expected output: (for user 2)
+---------+-----------+----------+------------+
| user_id | user_name | voter_id | voter_name |
+---------+-----------+----------+------------+
| 2 | Peter | 4 | Barman |
| 2 | Peter | 5 | Ali |
| 2 | Peter | 3 | John |
+---------+-----------+----------+------------+
Note: generally there should be one more row in the result like this:
| 2 | Peter | 2 | Peter |
But I don't want to get the ones which user_id and voter_id are the same. How can I do that?
My current query:
SELECT u.id, u.name, v.voter_id
FROM users u
INNER JOIN vote v
ON u.id = v.owner_post_id
WHERE u.id = 2 -- for user 2
You need to join to the users table twice, once for each side of the voting relationship.
SELECT t2.id AS user_id,
t2.name AS user_name,
t3.id AS voter_id,
t3.name AS voter_name
FROM vote t1
INNER JOIN users t2
ON t1.owner_post_id = t2.id
INNER JOIN users t3
ON t1.voter_id = t3.id
WHERE t1.owner_post_id = 2 AND
t1.voter_id <> t1.owner_post_id

How can I make a query which selects as nested?

I have two tables:
// users
+----+--------+
| id | name |
+----+--------+
| 1 | Jack |
| 2 | Peter |
| 3 | John |
| 4 | Barman |
| 5 | Ali |
+----+--------+
// friends
+---------+-----------+
| user_id | friend_id |
+---------+-----------+
| 1 | 3 |
| 1 | 4 |
| 1 | 5 |
| 3 | 1 |
| 3 | 2 |
| 3 | 4 |
| 5 | 2 |
+---------+-----------+
-- both user_id and friend_id columns refer to the id column of users table
I want to select all friends of Jack (id = 1). So here is the query:
select * from friend where user_id = 1
/* output
| 1 | 3 |
| 1 | 4 |
| 1 | 5 |
*/
Now I also want to select friends of Jack's friends. How can I do that?
Note, I don't want to select duplicate rows. So I want this output:
/* expected output:
| 1 | 3 |
| 1 | 4 |
| 1 | 5 |
| 3 | 2 |
| 3 | 4 |
| 5 | 2 |
*/
Add a IN clause with all friends of Jack use distinct user_id, friend_id
select distinct f1.user_id, f1.friend_id
from friend f1
where user_id = 1
or
user_id in (select f2.friend_id
from friend f2
where user_id = 1);
select distinct
f2.*
from
friend f1,
friend f2
where
f1.user_id = 1 and
(f1.friend_id = f2.user_id or f2.user_id = 1)
This still includes duplicates with opposite directions (it considers A--friend-->B as not being the same as B--friend-->A)

mySQL Table Join - Wrong Answer

I'm quite new to mySQL queries and struggling to achieve the result I require.
I have two tables of user information that I need to present. The tables are as follows:
users
+----+------------------+
| id | email |
+----+------------------+
| 1 | joe#hotmail.com |
| 2 | john#hotmail.com |
| 3 | fred#hatmail.com |
+----+------------------+
user_detail
+----------+--------+--------+
| detailid | userid | detail |
+----------+--------+--------+
| 1 | 1 | Joe |
| 2 | 1 | Soap |
| 1 | 2 | John |
| 2 | 2 | Doe |
| 1 | 3 | Fred |
| 2 | 3 | Bloggs |
+----------+--------+--------+
I have constructed the following query which joins the tables:
SELECT id, detail , email
FROM users
LEFT JOIN user_detail
ON users.id=user_detail.userid
ORDER by id
The query produces this result:
+--------+--------+------------------+
| userid | detail | email |
+--------+--------+------------------+
| 1 | Joe | joe#hotmail.com |
| 1 | Soap | joe#hotmail.com |
| 2 | John | john#hotmail.com |
| 2 | Doe | john#hotmail.com |
| 3 | Fred | fred#hatmail.com |
| 3 | Bloggs | fred#hatmail.com |
+--------+--------+------------------+
What I'm struggling to achieve is this:
+--------+---------+---------+------------------+
| userid | detail1 | detail2 | email |
+--------+---------+---------+------------------+
| 1 | Joe | Soap | joe#hotmail.com |
| 2 | John | Doe | john#hotmail.com |
| 3 | Fred | Bloggs | fred#hatmail.com |
+--------+---------+---------+------------------+
Could you please help and point me in the right direction?
SELECT id,
MAX(CASE WHEN detaildid=1 THEN detail END) as detail1,
MAX(CASE WHEN detaildid=2 THEN detail END) as detail2,
email
FROM users
LEFT JOIN user_detail
ON users.id=user_detail.userid
GROUP BY id,email
ORDER by id
This can be written dynamically if you have many detailids.
You can join the same table twice, once for detail id 1 and another instance for detail id 2
SELECT id, d1.detail, d2.detail, email
FROM users u
LEFT JOIN user_detail d1
ON u.id = d1.userid
AND d1.detailid = 1
LEFT JOIN user_detail d2
ON u.id = d2.userid
AND d2.detailid = 2
ORDER BY ID

MySQL, Join two rows from one table and ignore doublons

I have a table "user" like this :
| uid | username |
| 1 | Jack |
| 2 | John |
| 3 | Robert |
Using my request :
SELECT u1.username, u2.username FROM user u1 JOIN user u2
Using this request, I get a table like this :
| uid | username | uid | username |
| 1 | Jack | 1 | Jack |
| 1 | Jack | 2 | John |
| 1 | Jack | 3 | Robert |
| 2 | John | 1 | Jack |
| 2 | John | 2 | John |
| 2 | John | 3 | Robert |
| 3 | Robert | 1 | Jack |
| 3 | Robert | 2 | John |
| 3 | Robert | 3 | Robert |
How can I remove one of these duets?
| 1 | Jack | 2 | John |
| 2 | John | 1 | Jack |
You want all combinations of User table 1 with User table 2. I believe this would accomplish this:
SELECT u1.id, u1.name, u2.id u2.name
FROM User u1
INNER JOIN User u2
WHERE u1.id >= u2.id
This would give the following result:
| uid | username | uid | username |
| 1 | Jack | 1 | Jack |
| 2 | John | 1 | Jack |
| 2 | John | 2 | John |
| 3 | Robert | 1 | Jack |
| 3 | Robert | 2 | John |
| 3 | Robert | 3 | Robert |

Add an inner join to mySQL GROUP_CONCAT statement

Problem: I have a GROUP_CONCAT query that is working as intended, except I'd like to make the concat a joined answer, not the raw ID field.
Current query:
SELECT user.user_id, user.user, GROUP_CONCAT(user_roles.roleID separator ', ') roles
FROM user
JOIN user_roles ON user.user_ID = user_roles.user_ID
GROUP BY users.user_ID, users.user
Gives result:
+----------+---------+----------------------------+
| user_ID | user | roles |
+----------+---------+----------------------------+
| 1 | Smith | 1, 3 |
+----------+---------+----------------------------+
| 2 | Jones | 1, 2, 3 |
+----------+---------+----------------------------+
Desired result:
+----------+---------+----------------------------+
| user_ID | user | roles |
+----------+---------+----------------------------+
| 1 | Smith | Admin, Other |
+----------+---------+----------------------------+
| 2 | Jones | Admin, Staff, Other |
+----------+---------+----------------------------+
User table:
+----------+---------+
| user_ID | user |
+----------+---------+
| 1 | Smith |
+----------+---------+
| 2 | Jones |
+----------+---------+
*users_roles table:*
+----------+---------+
| user_ID | role_ID |
+----------+---------+
| 1 | 1 |
+----------+---------+
| 2 | 1 |
+----------+---------+
| 2 | 2 |
+----------+---------+
| 2 | 3 |
+----------+---------+
| 1 | 3 |
+----------+---------+
roles table:
+----------+-----------+
| role_ID | role_name |
+----------+-----------+
| 1 | Admin |
+----------+-----------+
| 2 | Staff |
+----------+-----------+
| 3 | Other |
+----------+-----------+
try the following query
SELECT user.user_id, user.user, GROUP_CONCAT(roles.role_name separator ', ') roles
FROM user
JOIN user_roles ON user.user_ID = user_roles.user_ID
JOIN roles ON user_roles.role_ID= user_roles.role_ID
GROUP BY users.user_ID, users.user