mySQL SELECT query from multiple tables - mysql

I need a help with mySQL SELECT query from multiple tables. I have got four tables: school, discipline, pupils and teams.
School table looks like:
+------+---------+---------------+----------+
| id | name | discipline_id | pupil_id |
+------+---------+---------------+----------+
| 1 | one | 2 | 5 |
+------+---------+---------------+----------+
| 2 | two | 3 | 8 |
+------+---------+---------------+----------+
| 3 | three | 4 | 12 |
+------+---------+---------------+----------+
Discipline table looks like:
+------+---------+
| id | name |
+------+---------+
| 1 | math |
+------+---------+
| 2 | bio |
+------+---------+
| 3 | liter |
+------+---------+
| 4 | geo |
+------+---------+
Teams table looks like:
+------+---------+---------------+-----------+
| id | name | school_id | member_id |
+------+---------+---------------+-----------+
| 1 | T1 | 1 | 3 |
+------+---------+---------------+-----------+
| 2 | T2 | 3 | 3 |
+------+---------+---------------+-----------+
| 3 | T3 | 2 | 9 |
+------+---------+---------------+-----------+
The result of disciplines I need to get with a "SELECT from discipline..." query by "member_id = 3" is:
+-----------------+---------------+
| discipline_name | discipline_id |
+-----------------+---------------+
| bio | 2 |
+-----------------+---------------+
| geo | 4 |
+-----------------+---------------+
By matching member's school and then getting its discipline, if it makes sense...Is it possible to do with just one mySQL query?
Type of: member_id 3 => school_id 1,3 => discipline_id = show related disciplines names and ids which are 2, 4
Thank you very much...

Your goal is not clear or makes no sense to me.
But here is what you are literally asking for:
SELECT
s.discipline_id
d.name
FROM teams t
LEFT JOIN school s
ON s.id = t.school_id
LEFT JOIN discipline d
ON d.id = s.discipline_id
WHERE t.member_id = 3

Related

Select rows that has common relationship

I have the following table:
Book
| id | book_title |
|----|------------|
| 1 | a |
| 2 | b |
| 3 | c |
| 4 | d |
Teacher:
| id | teacher_name |
|----|--------------|
| 1 | a |
| 2 | b |
| 3 | c |
| 4 | d |
Education stage:
| id | education_stage_name |
|----|----------------------|
| 1 | a |
| 2 | b |
| 3 | c |
| 4 | d |
The relationship between book and education stage:
| book_id | education_stage_id |
|---------|--------------------|
| 1 | 1 |
| 1 | 2 |
| 2 | 3 |
| 3 | 4 |
And the relationship between book and teacher:
| book_id | teacher_id |
|---------|------------|
| 1 | 1 |
| 1 | 4 |
| 2 | 3 |
| 3 | 4 |
Now I want to select books, which has the same education stages as a teacher with id=1
So the result table should look like this:
| book_id | title |
|---------|-------|
| 1 | a |
Because only the education stage with id=1 is assigned to the book and the teacher with id=1 at the same time.
Here is the fiddle, but I don't know even how to start with this query.
Is there anyone that has some ideas on how to write this query?
Is it possible to write it with DQL language?
This doesn't take anything complex, if all records will always exist, you can inner join on all tables:
select
Book.id as book_id,
Book.book_title,
Teacher.id as teacher_id,
Teacher.teacher_name
from Book
inner join book_education_stage bes on bes.book_id = Book.id
inner join Education_Stage es on es.id = bes.education_stage_id
inner join teacher_education_stage tes on tes.book_id = Book.id
inner join Teacher on tes.teacher_id = Teacher.id
Result:
book_id
book_title
teacher_id
teacher_name
1
a
1
a
1
a
1
a
1
a
4
d
1
a
4
d
2
b
3
c
3
c
4
d
Here is the DB Fiddle if you're interested.

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!

MySQL joining 3 tables using UNION

This question is a little long so that it would be clear, thanks in advance!
Introduction
I currently have 3 tables using a many-to-many relationship. I need to query all 3 tables and combine them into 1 table.
Problem
I have tried this query:
SELECT * FROM `login` LEFT JOIN membership ON login.id = membership.login_id UNION SELECT * FROM `login` RIGHT JOIN membership ON login.id = membership.login_id
And it returns:
+----+------+----------+
| id | name | group_id |
+----+------+----------+
| 1 | Tom | 6 |
| 2 | John | 8 |
| 3 | Jane | 4 |
+----+------+----------+
Question
I need it to also include the group_name. This is my desired output:
+----+------+----------+------------+
| id | name | group_id | group_name |
+----+------+----------+------------+
| 1 | Tom | 6 | Red |
| 2 | John | 8 | Brown |
| 3 | Jane | 4 | Purple |
+----+------+----------+------------+
Tables
login Table
A list of all users with auto-increment id
+----+------+
| id | name |
+----+------+
| 1 | Tom |
| 2 | John |
| 3 | Jane |
+----+------+
group Table
A list of all groups with the group_id and group_name
+----------+------------+
| group_id | group_name |
+----------+------------+
| 1 | Green |
| 2 | Blue |
| 3 | Yellow |
| 4 | Purple |
| 5 | Orange |
| 6 | Red |
| 7 | Pink |
| 8 | Brown |
+----------+------------+
membership Table
Stores information on which user belongs to which group
+----------+----------+
| login_id | group_id |
+----------+----------+
| 1 | 6 |
| 2 | 8 |
| 3 | 4 |
+----------+----------+
Join the group table as well and select the required fields from the tables.
SELECT l.id,l.name,m.group_id,g.group_name
FROM `login` l
LEFT JOIN `membership` m ON l.id = m.login_id
LEFT JOIN `group` g on g.group_id = m.group_id
Try this... :)
SELECT
`login`.`id`,
`login`.`name`,
`group`.`group_id`,
`group`.`group_name`
FROM
`membership`
INNER JOIN `login` ON (`membership`.`login_id` = `login`.`id`)
INNER JOIN `group` ON (`membership`.`group_id` = `group`.`group_id`)

Find unique/duplicated rows from has and belongs to many association

I have following DB structure:
Table cars:
+----+-----------------------+
| id | few other columns.... |
+----+-----------------------+
| 1 | ... |
| 2 | ... |
| 3 | ... |
+----+-----------------------+
Table properties:
+----+-------+
| id | name |
+----+-------+
| 1 | title |
| 2 | type |
| 3 | brand |
| 4 | color |
+----+-------+
Table cars_properties:
+----+--------+-------------+------------+
| id | car_id | property_id | txt |
+----+--------+-------------+------------+
| 1 | 1 | 1 | Volvo V70 |
| 2 | 1 | 2 | personal |
| 3 | 1 | 3 | Volvo |
| 4 | 1 | 4 | white |
| 5 | 2 | 1 | Volvo VV |
| 6 | 2 | 2 | personal |
| 7 | 2 | 3 | Volvo |
| 8 | 2 | 4 | blue |
| 9 | 3 | 1 | Volvo XXL |
| 10 | 3 | 2 | truck |
| 11 | 3 | 3 | Volvo |
| 12 | 3 | 4 | white |
+----+--------+-------------+------------+
I would like to get all cars that have unique/duplicated values in one or many properties. Currently I'm using this SQL pattern to get duplicates for car type and brand:
SELECT cars.id FROM cars
LEFT JOIN cars_properties AS cp_0 ON cp_0.car_id = cars.id AND cp_0.property_id = 2 # => type
LEFT JOIN cars_properties AS cp_1 ON cp_1.car_id = cars.id AND cp_1.property_id = 3 # => brand
INNER JOIN (
SELECT cp_0.txt AS type_txt, cp_1.txt AS brand_txt FROM cars
LEFT JOIN cars_properties AS cp_0 ON cp_0.car_id = cars.id AND cp_0.property_id = 2
LEFT JOIN cars_properties AS cp_1 ON cp_1.car_id = cars.id AND cp_1.property_id = 3
GROUP BY cp_0.txt, cp_1.txt
HAVING COUNT(cars.id) > 1
) dupes ON cp_0.txt=dupes.type_txt AND cp_1.txt=dupes.brand_txt;
And expected result is:
+----+
| id |
+----+
| 1 |
| 2 |
+----+
Explanation: Both cars with id = 1 and 2 has type and brand that is present in more than one car (multiple times).
As for unique cars, I'm just altering: HAVING COUNT(cars.id) = 1 and I want to find all rows where the combination of properties is present only in one car (once).
It works fine, but it's extremely slow with more than 2 properties I want to check.
I cannot change the DB structure, and I'm not sure how to optimize the query, or if there are better ways of achieving this.
It feels like I would need to implement counter table, where each property id and value (txt) would also store corresponding number of occurrences in cars, and update this counter on every insert/update/delete... But I still hope there is some better SQL, that could help. Do you know some? Any advice greatly appreciated, thanks!
PS: I tried to create fiddle for it, but after I build schema I cannot run any SQL on it. To quickly setup DB with data, you can check SQL Fiddle

Counting from another table [mysql]

I have one table like this:
+----+---------+-------------+
| id | site_id | search_term |
+----+---------+-------------+
| 1 | 2 | apple |
| 2 | 2 | banana |
| 3 | 3 | cheese |
| 4 | 1 | aubergine |
+----+---------+-------------+
And another like this:
+----+---------+-------------+
| id | site_id | search_term |
+----+---------+-------------+
| 1 | 2 | 1 |
| 2 | 2 | 2 |
| 3 | 2 | 1 |
| 4 | 2 | 1 |
| 5 | 3 | 3 |
| 6 | 1 | 4 |
+----+---------+-------------+
I want to find out how many times each search_term shows up in the 2nd table, and how many times.
In other words, from this data, if I was asking about site_id 2, I'd want this to be returned:
+-------------+-------+
| search_term | count |
+-------------+-------+
| apple | 3 |
| banana | 1 |
+-------------+-------+
I'm familiar with basic joins and such, as well as COUNT, but I'm not sure how to count things from another table.
Thanks!
You could join the tables together, and count the number of rows in the second table:
select t1.search_term
, count(t2.id)
from table1 t1
left join table2 t2
on t1.id = t2.search_term
group by t1.search_term
Give this a try:
select t1.search_term, count(*) from t1
join t2 on t1.id = t2.search_term and t1.site_id = t2.site_id
where t1.site_id = 2
group by t1.search_term