MySQL JOIN query - - mysql

I know this question has already asked here, but I can't figure this one out from the previous answers.
We've got 2 tables:
members
-----------------------
| id | country_iso_3 |
-----------------------
1 USA
2 DZA
3 FRA
4 ILI
5 USA
6 USA
members_details
-----------------------
| member_id | city |
-----------------------
1 AA
2 BB
3 CC
4 DD
5 EE
6 FF
Now I want to query members_details and select the cities which are from the same countries, here "AA", "EE" and "FF" should be the results (because the members are from USA)
I know how to compare different cols from different tables, but here we need to check the second table 'member_id' and the first table 'id (country_iso_3)' somehow!

Select city from members LEFT JOIN members_details
ON members.id = members_details.memberid Where country_iso_3 = 'USA'

Just JOIN the two tables, with a WHERE clause for the country you want to get the city of it like so:
SELECT md.city
FROM members m
INNER JOIN members_details md ON m.id = md.memberid
WHERE m.country_iso_3 = 'USA'
SQL Fiddle Demo

This should work, and not only for USA, but for any country which is listed more than once:
SELECT d.city
FROM members m,
members_details d
WHERE d.member_id = m.id
AND m.country_iso_3 IN (
SELECT country_iso_3
FROM members
GROUP BY 1
HAVING count(1) > 1
)

Related

SQL Select parent as column name and child as value

I am creating a database to store music.
There are different categories that each have sub categories. Example:
id name parentID
1 instrumentation null
2 solo_instrument null
3 Concert Band 1
4 Brass Band 1
5 Fanfare Band 1
6 Clarinet 2
7 Saxophone 2
8 Trumpet 2
On the other hand I have a table that stores the musicID that is linked to a categoryID
id categoryID musicID
1 4 1
2 8 1
3 3 2
4 6 2
I need the following result from a query:
musicID instrumentation solo_instrument
1 Brass Band Trumpet
2 Concert Band Clarinet
I have been told to use a tree structure as in the future it is likely that other categories are added and this should be able to support that. However, I am not able to figure out how to write a query to get the result above.
I kind of get the result I want when selecting first the instrumentation, second the solo_instrument, but this is all hardcoded and does not allow for music tracks to only have one parentID as I select them individually.
Is this even possible or should I overhaul my database structure? I'd like to see your recommendations.
You should be able to tackle this using conditional aggregation.
Query :
SELECT
mu.musicID,
MAX(CASE WHEN cp.name = 'instrumentation' THEN ca.name END) instrumentation,
MAX(CASE WHEN cp.name = 'solo_instrument' THEN ca.name END) solo_instrument
FROM
musics mu
INNER JOIN categories ca ON ca.id = mu.categoryID
INNER JOIN categories cp ON cp.id = ca.parentID
GROUP by mu.musicID
The INNER JOINs pull up the corresponding category, and then goes up one level to find the parent category. If new root categories are created, you would just need to add more MAX() columns to the query.
In this DB Fiddle demo with your sample data, the query returns :
| musicID | instrumentation | solo_instrument |
| ------- | --------------- | --------------- |
| 1 | Brass Band | Trumpet |
| 2 | Concert Band | Clarinet |
First you group by musicid in table_music and the join twice to table_categories:
select t.musicid, c1.name instrumentation, c2.name solo_instrument
from (
select musicid, min(categoryid) instrumentationid, max(categoryid) solo_instrumentid
from table_music
group by musicid
) t inner join table_categories c1
on c1.id = t.instrumentationid
inner join table_categories c2
on c2.id = t.solo_instrumentid
order by t.musicid

Mysql trigger that multiplies two values from different tables, totalizes by groups and adds values to another column

I've been going around this for a while and there isno way I can figure it out. Let's say I have these three tables:
Users
Name | Basket value
-------+---------------
John | ???
-------+---------------
Pierre | ???
Items
User | Item | Amount
-----------+------------+------------
John | Pears | 2
-----------+------------+------------
Pierre | Pears | 1
-----------+------------+------------
Pierre | Apples | 3
Market_ prices
Item | Price
------------+---------------
Pears | 2.35
------------+---------------
Apples | 2.56
Basket value is needed. So for each row in ITEMS it must multiply its AMOUNT by MARKET_PRICES[PRICE] and sum all the results grouped by USER and place this result in USERS[total items value]. But how could the syntax be elaborated to take this to practice?
Many thanks in advance for the help.
One approach is to join the relevant tables:
SELECT u.name, SUM(i.amount*m.price)
FROM users u
JOIN items i ON u.name = i.user
JOIN market_prices m ON i.item = m.item
GROUP BY u.name;
(SQLfiddle of this is at: http://sqlfiddle.com/#!9/ec224/6 - I added a few other rows to the tables to test more complexity, so the totals aren't what you'd get from your example. Specifically, I added Bananas 3.75 to the Market_prices table and John Apples 3 and Pierre Bananas 5 to the Items table.)
The goal here is to link the information in all three tables through shared fields (via the JOIN), while also GROUPing and creating a SUM of the calculated costs as a product of market price and number of items.
---- edited based on comments ----
To do this as an update, you could try:
UPDATE users
SET basket_value = (SELECT basket FROM
(SELECT name, SUM(i.amount*m.price) AS basket
FROM users u JOIN items i ON u.name = i.username
JOIN market_prices m ON i.item = m.item
GROUP BY u.name) q1 WHERE q1.name = users.name);
I have a feeling there is a more elegant solution, but this works. Modified SQLFiddle is: http://sqlfiddle.com/#!9/56245a/1
SELECT User, SUM(rev) AS basket_price
FROM
(
SELECT a.User AS User, a.Amount*b.Price AS rev
FROM Items a
LEFT JOIN
Market_Prices b
ON a.Item = b.Item
) a1
GROUP BY User

I want to fetch data from 2 different table

I want to fetch result master.category wise suppose if i have
$category ='doctor'
then how can i get the result? i have drawn the tables below and expected result also, Please help me. thanks
table name->Master
------------------
id label category
1 expertise doctor
2 fee doctor
3 appontment doctor
4 services lawyer
5 qualification student
table name->Field
------------------
id label_id Information
1 1 desntist
2 1 general_physician
3 1 general_surgeons
4 4 criminal_law
5 5 civil_law
expected result
--------------------
expertise
dentist
general_physician
general_surgeons
Perform a JOIN like
select f.information as 'expertise'
from field f
join master m on m.id = f.label_id
where m.category = 'doctor';
its query give all information by master's id
SELECT m.label, GROUP_CONCAT(Information)
FROM Master m
JOIN Field f
ON m.id = f.label_id
WHERE m.category = 'doctor'

Mysql left join table not between dates

I have the following issue, I've got 3 tables the first one is called courses where I have
courses| id | start | end |
--------------------------------------
1 2012-10-12 | 2012-11-12 |
students| id | available_start | available_end |
-------------------------------------------------
1 2012-10-13 2012-11-11
2 2012-11-06 2012-11-08
students_to_courses | student_id | course_id |
-------------------------------------------------
1 1
So I'm trying to find which students are available for courses periods. So if the student is added to student_to_courses and dates are between the course dates I don't need it.
I've got the feeling that the query should be with a sub query but I really don't understand them. My query now is looking like this but doesn't work properly.
SELECT s.id
FROM (`students` s)
LEFT JOIN `student_to_course` s2c ON `s2c`.`student_id` = `s`.`id`
LEFT JOIN `courses` assigned_2_course ON `s2c`.`course_id` = `assigned_2_course`.`id`
LEFT JOIN `courses` c ON `c`.`id` = 1
WHERE
(
(s.available_start NOT BETWEEN assigned_2_course.start AND assigned_2_course.end
AND
s.aviailable_end NOT BETWEEN assigned_2_course.start AND assigned_2_course.end
) OR assigned_2_course.end IS NULL)
AND
`s`.`available_start` BETWEEN c.start AND c.end
AND `s`.`available_end` <= c.end
GROUP BY `s`.`id`
ORDER BY `s`.`id` desc
Here is http://sqlfiddle.com/#!2/49c11/1
now works, but doesn't remove the students which are assigned in other courses with same dates how you can see I'm trying to get available students for course 3 which starts 02-03 and ends 02-08, student 2 is in course 3 so is not shown, student 1 is in course 2 which starts 01-03 and ends 03-01 so shouldn't be available.
Any help will be appreciated.
I used your SQL fiddle (but added another student record) http://sqlfiddle.com/#!2/246645/1
try this to find all students that could attend course 3 because they are not in a class during that time:
SELECT student.*
FROM student
JOIN course
ON course.id = 3
AND student.available_start <= course.`start`
AND student.available_end >= course.`end`
WHERE NOT EXISTS
(SELECT *
FROM student_to_course
JOIN course AS c
ON student_to_course.course_id = c.id
WHERE student.id = student_to_course.student_id
AND (course.`start` BETWEEN c.`start` AND c.`end`
OR
course.`end` BETWEEN c.`start` AND c.`end`
OR
c.`start` BETWEEN course.`start` AND course.`end`));

MySQL - Retrieve row value from different table depending on value of row in a table

I have a feeling CASE should be used here but I am not sure. I'm trying to take the sex (m/f) from the general table and depending on the sex, get the build from the corresponding table. For example, when the sex is m, the query should know that by going to the males table and selecting the male_build. I put together an output along with a sample query to give an idea of what I'm trying to accomplish:
members table
member_id | member_name
------------------------
1 Herb
2 Karen
3 Megan
4 Pablo
males table
male_id | member_id | male_build
---------------------------------
1 1 muscular
2 4 fat
females table
female_id | member_id | female_build
-------------------------------------
1 2 thin
2 3 fat
general table
general_id | member_id | sex
-----------------------------
1 1 m
2 2 f
3 3 f
4 4 m
The output should be like this:
1. Herb is a muscular male.
2. Karen is a thin female.
3. Megan is a fat female.
4. Pablo is a fat male.
-> query = "SELECT g.general_id, g.member_id, g.sex,
(CASE when g.sex=m THEN SELECT ma.male_build AS build
FROM males ma WHERE ma.member_id=g.member_id,
CASE when g.sex=f THEN SELECT fe.female_build AS build
FROM females fe WHERE fe.member_id=g.member_id),
m.member_name
FROM members m
JOIN members m ON g.member_id=m.member_id
WHERE g.sex='m' OR g.sex='f'";
Looking for an efficient query for this task.
When you are having to do queries like this, it is a good idea to rethink your database design schemas. That being said, this should work:
SELECT mem.*, g.*, coalesce(m.male_build, f.female_build) as build
from members_table mem
inner join general g on mem.meber_id = g.member_id
left join males m on mem.member_id = m.member_id
left join females f on mem.member_id = f.member_id
Select M.member_name + ' is a '
+ gender_attributes.sex_name
+ ' '
+ gender_attributes.build
From members As M
Join general_table As G
On G.member_id = M. member_id
Join (
Select 'm' As sex, 'male' As sex_name, male_id as id, member_id, male_build As build
From males_table
Union All
Select 'f' As sex, 'female', female_id, member_id, female_build
From females_table
) As gender_attributes
On gender_attributes.sex = G.sex
And gender_attributes.member_id = M.member_id
I'd just have a build_types table and a foreign key on your members table. It may be an edge case, but you can get muscular women, and thin guys.