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)
Related
I have these 2 tables
+-------------------+ +----------------------------------------------+
| movies | | ratings |
+-------------------+ +----------------------------------------------+
| Id | Name | | Id_movie | id_user | id_rating | user_rate |
|-------------------| |----------------------------------------------|
| 1 | movie 1 | | 1 | 20 | 1 | 5 |
| 2 | movie 2 | | 1 | 21 | 2 | 3 |
| 3 | movie 3 | | 1 | 22 | 3 | 4 |
+-------------------+ | 2 | 21 | 3 | 5 |
| 2 | 22 | 3 | 4 |
| 3 | 22 | 3 | 5 |
+----------------------------------------------+
i want to get
+----------------------------------------+
| movies |
+----------------------------------------+
| Id_user | id_movie | Name |
|----------------------------------------|
| 20 | 2 | movie 2 |
| 20 | 3 | movie 3 |
+----------------------------------------+
condition where user = 20 didnt rate movie 2 & 3. is it possible?
Can somebody help me? thank you
You must generate all combinations user-movie then test each combination for its absence in ratings.
SELECT user.user id_user,
movies.id id_movie,
movies.name
FROM ( SELECT 20 AS user ) AS user -- needed user(s)
-- for all users use
-- ( SELECT DISTINCT user FROM ratings ) AS user
CROSS JOIN movies -- cross join generates all combinations
WHERE NOT EXISTS ( SELECT NULL -- select only non-existent combinations
FROM ratings
WHERE ratings.id_user = user.user
AND ratings.id_movie = movies.id )
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
)
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
I'm new in SQL queries. I have a problem with the query.
I have table books:
+----+-------+--------+-----------+
| id | title | author | publisher |
+----+-------+--------+-----------+
| 1 | Book1 | 1 | 1 |
| 2 | Book2 | 1 | 2 |
| 3 | Book3 | 2 | 1 |
| 4 | Book4 | 2 | 2 |
| 5 | Book5 | 2 | 3 |
+----+-------+--------+-----------+
And I'm have another table, which contains copies of books with given book_id.
+----+---------+
| id | book_id |
+----+---------+
| 1 | 1 |
| 2 | 1 |
| 3 | 1 |
| 4 | 2 |
| 5 | 2 |
| 6 | 3 |
| 7 | 4 |
| 8 | 4 |
| 9 | 5 |
+----+---------+
All I need is to merge these two tables into one to have table sorted by amount of book copies.
I found solution to get table sorted by amount of book copies:
select book_copies.book_id, count(*) total_count
from book_copies
group by book_id
having count(*) > 0
order by count(*) desc;
+---------+-------------+
| book_id | total_count |
+---------+-------------+
| 1 | 3 |
| 2 | 2 |
| 4 | 2 |
| 3 | 1 |
| 5 | 1 |
+---------+-------------+
Now I don't know how to merge them.
I've tried like this:
select books.title from books
left join
(select book_copies.book_id, count(*) total_count
from book_copies
group by book_id
having count(*) > 0
order by count(*) desc)
as total_table on books.id = total_table.book_id;
But all I get was this:
+-------+
| title |
+-------+
| Book1 |
| Book2 |
| Book3 |
| Book4 |
| Book5 |
+-------+
Could you help me please?
EDIT: by merging I meant smth like this:
+-------+--------+-----------+-----+
| title | author | publisher | tot |
+-------+--------+-----------+-----+
| Book1 | 1 | 1 | 3 |
| Book2 | 1 | 2 | 2 |
| Book4 | 2 | 2 | 2 |
| Book3 | 2 | 1 | 1 |
+-------+--------+-----------+-----+
Many thanks to #Marco for the answer!
Dmitriy
I think you could try:
SELECT b.title, b.author, b.publisher, COUNT(bc.book_id) AS tot
FROM books b LEFT JOIN book_copies bc
ON b.id = bc.book_id
GROUP BY b.id
EDITED:
If you want sort, you can try
SELECT * FROM
(SELECT b.title, b.author, b.publisher, COUNT(bc.book_id) AS tot
FROM books b LEFT JOIN book_copies bc
ON b.id = bc.book_id
GROUP BY b.id) g
ORDER BY g.tot DESC
I have following tables:
table users - PRIMARY KEY (user_id)
+---------+----------+-----------+
| user_id | username | realname |
+---------+----------+-----------+
| 1 | peterpan | Peter Pan |
| 2 | bobfred | Bod Fred |
| 3 | sallybe | Sally Be |
| 6 | petersep | Peter Sep |
+---------+----------+-----------+
table users_groups - PRIMARY KEY (user_id, group_id)
+---------+----------+
| user_id | group_id |
+---------+----------+
| 1 | 1 |
| 1 | 2 |
| 2 | 1 |
| 2 | 2 |
| 3 | 6 |
| 3 | 9 |
| 6 | 6 |
| 6 | 9 |
+---------+----------+
table game - PRIMARY KEY (id)
+----+-------+
| id | game |
+----+-------+
| 1 | Game1 |
| 2 | Game2 |
| 6 | Game6 |
| 9 | Game9 |
+----+-------+
table groups - PRIMARY KEY(group_id)
+----------+--------------+---------------+
| group_id | group_name | group_desc |
+----------+--------------+---------------+
| 1 | Groupname1 | Description1 |
| 2 | Groupname2 | Description2 |
+----------+--------------+---------------+
table group_game - PRIMARY KEY(group_id, game_id)
+----------+----------+
| group_id | game_id |
+----------+----------+
| 1 | 1 |
| 1 | 2 |
| 2 | 6 |
| 2 | 9 |
+----------+----------+
I want to display this (like a group list):
+----+------------+--------------+---------------------+--------------+
| id | group name | group desc | group members | group games |
+----+------------+--------------+---------------------+--------------+
| 1 | GroupName1 | Description1 | Peter Pan, Bob Fred | Game1, Game2 |
| 2 | GroupName2 | Description2 | Sally Be, Peter Sep | Game6, Game9 |
+----+------------+--------------+---------------------+--------------+
Now I have this query but it gives me no rows (no error, just zero rows):
SELECT
g.group_name,
g.group_id,
g.group_desc,
GROUP_CONCAT(DISTINCT ga.game SEPARATOR ', ') AS games,
GROUP_CONCAT(DISTINCT u.realname SEPARATOR ', ') AS users
FROM groups g
LEFT JOIN users_groups ug1
ON g.group_id=ug1.group_id
LEFT JOIN users u
ON ug1.user_id=u.user_id
LEFT JOIN group_game gg
ON g.group_id=gg.group_id
LEFT JOIN game ga
ON gg.game_id=ga.id
GROUP BY g.group_name
How can I solve this problem or how can I write this query?
I just want to show a group list with all information (like group information, users of the groups, games of this group).