How can I match common rows? - mysql

I have a table like this:
// friends
+----+---------+--------+
| id | user_id | friend |
+----+---------+--------+
| 1 | 1 | Peter |
| 2 | 1 | Martin |
| 3 | 2 | Jack |
| 4 | 1 | Barman |
| 5 | 3 | Peter |
| 6 | 1 | Jack |
| 7 | 3 | David |
| 8 | 2 | David |
| 9 | 3 | Martin |
+----+---------+--------+
Now I have two user_ids. For example 1 and 3. Now I want to match the rows which have common friends. So this is expected result:
| Peter |
| Martin |
Because Peter and Martin are common for both ids 1 and 3.
Is doing that possible by pure sql ?

You can do a self-join of the friends table, with the following three conditions being required to match records from both sides of the join:
The user_id from the first table is 1
The user_id from the second table is 3
The friends match (i.e. are shared by both sides)
SELECT t1.friend
FROM friends t1
INNER JOIN friends t2
ON t1.user_id = 1 AND
t2.user_id = 3 AND
t1.friend = t2.friend
If you have indices setup properly, I would expect this to run faster than an aggregation approach.
Demo here:
Rextester

Try this:
SELECT friend
FROM friends
WHERE user_id IN (1, 3)
GROUP BY friend HAVING COUNT(DISTINCT friend) = 2;

Another way
SELECT friend
FROM t
GROUP BY friend
HAVING SUM(user_id =1)>0
AND SUM(user_id =3)>0

Related

relating two MySQL tables with followers

Good afternoon, I'm not very expert in mysql.
but I would like to relate my table followers to show.
Here is an example of what I need to do.
thank you very much
table number1
id | user | example
--------------------------
1 | john | tall
2 | dave | fat
3 | maria | pretty
4 | example | love
4 | andres | hope
table number2 followers
id | id_user | user_table1
--------------------------
1 | fran | red
2 | love | dave
3 | maria | dave
4 | maria | dave
5 | maria | dave
selet * from number1 where user = 'dave'
result:
2 | dave | fat
but I would like to relate the table number2 and number2.
I need this
result:
1 | dave | fat
2 | maria | pretty
3 | example | love
I'm not quite sure the relation you need actually but based on your example. I think you need all field which related to 'dave'. Try this :
select distinct a.id, a.user, a.example
from number1 a inner join number2 b
on a.user = b.user_table1
or a.user = b.id_user
or a.example = b.id_user
where b.user_table1 = 'dave'
order by a.id
Example : http://sqlfiddle.com/#!9/9f2f79/16

Finding out only certain Master items from Details table in a Master-Details table relationship

I've been trying to get this going for hours and haven't figured this out yet.
Say I've got 2 tables - master and details.
master/detail has the following data
master table
+------+-------+
| id | name |
+------+-------+
| 1 | jeff |
| 2 | simon |
| 3 | andy |
| 4 | jerry |
+------+-------+
details table
+----+-----------+---------+
| id | master_id | tag |
+----+-----------+---------+
| 1 | 1 | WINDOWS |
| 2 | 1 | MAC |
| 3 | 2 | MAC |
| 4 | 3 | WINDOWS |
| 5 | 3 | MAC |
| 6 | 3 | LINUX |
| 7 | 4 | MAC |
+----+-----------+---------+
how do I select the master records which has both tags 'WINDOWS', 'MAC'.
So it should only return master_id 1 and 3 which is jeff and andy only.
If I do a
select distinct(master_id) from details where tag in ('WINDOWS', 'MAC')
it gives me all of them.
Sorry for the newbie question but if anyone can help, it'll be much appreciated.
You need simple GROUP BY with HAVING clause :
select master_id
from details
where tag in ('WINDOWS', 'MAC')
group by master_id
having count(*) = 2;
If details table has duplicate tags for master_id then you need count(distinct tag).
YOu could use a join with count having 2 value only for tag
select distinct master_id
from detail
inner join (
select master_id from detail
group by master_id
having count(distinct tag) = 2
) t on t.master_id = detail.master_id and detail.tag in ('WINDOWS', 'MAC')

mysql - Limit a query with left join

I have 2 tables like this:
Table person
id | name
---------
1 | john
2 | mike
3 | carl
4 | keny
5 | anna
Table vehicle
owner | vechicle
----------------
1 | RTA457
3 | GSW684
3 | GKI321
3 | SNE798
5 | YTT662
So, I want to make a query joining both tables, something like this:
SELECT * FROM person LEFT JOIN vehicle ON person.id=vehicle.owner
Getting these results
id | name | owner | vechicle
----------------------------
1 | john | 1 | RTA457
2 | mike | NULL | NULL
3 | carl | 3 | GSW684
3 | carl | 3 | GKI321
3 | carl | 3 | SNE798
4 | keny | NULL | NULL
5 | anna | 5 | YTT662
Finally, I want to limit it to 3 persons, showing all their vehicles, like this:
id | name | owner | vechicle
----------------------------
1 | john | 1 | RTA457
2 | mike | NULL | NULL
3 | carl | 3 | GSW684
3 | carl | 3 | GKI321
3 | carl | 3 | SNE798
There is any way to do it?
May help with a subquery
SELECT
*
FROM
(SELECT * FROM person LIMIT 3) t
LEFT JOIN vehicle ON t.id = vehicle.owner
Didn't try it, but something like this:
SELECT * FROM person
LEFT JOIN vehicle ON person.id = vehicle.owner
WHERE person.id IN (SELECT ID FROM PERSON LIMIT 3);
You could simply have your query as such:
SELECT * FROM person LEFT JOIN vehicle ON person.id=vehicle.owner LIMIT 10;
This SO could be handy as well. Hope this helps!

Adding sum from 2 different tables

I have something like this
2 tables:
videos
members
In the members table I have the name of each member:
1 Tom
2 Bob
3 Zack
4 Dan
5 Casey
In the videos table I have a column named members and I have the names in there seperated by commas
1. Tom,Dan
2. Casey,Zack,Bob
3. Tom,Casey,Dan,Zack
4. Zack,Bob,Dan
I'm trying to display how many times each member appears to get these results:
1 Tom = 2
2 Bob = 2
3 Zack = 3
4 Dan = 2
5 Casey = 2
Do I need to do something like SELECT SUM(members) WHERE and use LIKE?
I would strongly suggest to normalize your data as others suggested.
Based on your current design you can use FIND_IN_SET to accomplish the result you want.
SELECT
M.id,
M.name,
COUNT(*) total
FROM members M
INNER JOIN videos V ON FIND_IN_SET(M.name,V.members) > 0
GROUP BY M.name
ORDER BY M.id
See Demo
Running this query on your given data set you will get output like below:
| id | name | total |
|----|-------|-------|
| 1 | Tom | 2 |
| 2 | Bob | 2 |
| 3 | Zack | 3 |
| 4 | Dan | 3 |
| 5 | Casey | 2 |
A must read
Is storing a delimited list in a database column really that bad?
More
This is how your vidoes table would look like if you normalize your data:
videos
id member_id
One way to go is to join the two tables, based on a like expression:
SELECT members.name, count (*) as counter from members inner join videos
ON videos.members like CONCAT('%,',members.name,',%')
GROUP BY members.name;
But I think the better solution will be like #e4c5 said in the comment - you need to normalize the data. the videos table should look like:
+---+-------+
|ID | MEMBER|
+---+-------+
| 1 | Tom |
| 1 | Dan |
| 2 | Casey |
| 2 | Zack |
| 2 | Bob |
| 3 | Tom |
| 3 | Casey |
| 3 | Dan |
| 3 | Zack |
| 4 | Zack |
| 4 | Bob |
| 4 | Dan |
+---+-------+
That way, you can simply count on this table

Select Distinct Set Common to Subset From Join Table

Given a join table for m-2-m relationship between booth and user
+-----------+------------------+
| booth_id | user_id |
+-----------+------------------+
| 1 | 1 |
| 1 | 2 |
| 1 | 5 |
| 1 | 9 |
| 2 | 1 |
| 2 | 2 |
| 2 | 5 |
| 2 | 10 |
| 3 | 1 |
| 3 | 2 |
| 3 | 3 |
| 3 | 4 |
| 3 | 6 |
| 3 | 11 |
+-----------+------------------+
How can I get a distinct set of booth records that are common between a subset of user ids? For example, if I am given user_id values of 1,2,3, I expect the result set to include only booth with id 3 since it is the only common booth in the join table above between all user_id's provided.
I'm hoping I'm missing a keyword in MySQL to accompish this. The furthest I've come so far is using ... user_id = all (1,2,3) but this is always returning an empty result set (I believe I understand why it is though).
The SQL query for this will be:
select booth_id from table1 where [user_id]
in (1,2,3) group by booth_id having count(booth_id) =
(select count(distinct([user_id])) from table1 where [user_id] in (1,2,3))
If this could help you creating the MySQL query.