Mysql select with multiple tables and multiple foreign keys - mysql

If I have three tables like:
suppliers (sID: integer, sName: varchar, description: varchar); With sID as primary key
+-----+-----------+-------------+
| sID | SName | description |
+-----+-----------+-------------+
| 1 | Supplier1 | Desc1 |
| 2 | Supplier2 | Desc2 |
| 3 | Supplier3 | Desc3 |
| 4 | Supplier4 | Desc4 |
| ... | ... | ... |
+-----+-----------+-------------+
products (pID: integer, pName: varchar, size: varchar); With pID as primary key
+-----+----------+------+
| pID | pName | size |
+-----+----------+------+
| 1 | Product1 | S |
| 2 | Product2 | M |
| 3 | Product3 | B |
| 4 | Product4 | M |
| ... | ... | ... |
+-----+----------+------+
menu (sID: integer, pID: integer, cost: varchar); with sID and pID as foreign keys
+-----+-----+------+
| sID | pId | cost |
+-----+-----+------+
| 1 | 4 | 10 |
| 2 | 16 | 20 |
| 8 | 1 | 5 |
| 8 | 2 | 8 |
| ... | ... | ... |
+-----+-----+------+
The only relation between suppliers and products is given by the menu table.
How can I select the names of all suppliers that supply all products?
Thanks for any help!

Here is how you would get the ids. Simply aggregate and count:
select m.sid
from menu m
group by m.sid
having count(distinct pid) = (select count(*) from products);
I'll leave it to you to get the supplier name, which you can do using in, exists, join, or even a correlated subquery.

Related

How do I query a three-level structure in two joined tables?

There are two tables,
Table A has a three-level structure that looks like
| id | name | level | up_level_id |
| :------- | :-------: | :------: | ----------:|
| 1 | lv1_name1 | 1 | null |
| 2 | lv1_name2 | 1 | null |
| 3 | lv2_name1 | 2 | 1 |
| 4 | lv2_name2 | 2 | 2 |
| 5 | lv3_name1 | 3 | 3 |
| 6 | lv3_name2 | 3 | 3 |
| 7 | lv3_name3 | 3 | 4 |
| 8 | lv3_name4 | 3 | 4 |
Table B looks like
| amount | org_id |
| -------- | -------- |
| 12,000 | 5 |
| 15,000 | 6 |
| 20,000 | 7 |
| 18,000 | 8 |
Table A and Table B can be joined on A.id=B.org_id, but they are all at the level-3 of Table A(Only level-3 has their amount)
I want to query the top-level name,level-1 name, and the summary amount that looks like
| sum_amount | top_lvl_name |
| -------- | -------- |
| 27,000 | lv1_name1 |
| 38,000 | lv1_name2 |
For Testing, I have already accomplished the query of the level-1 name from the level-3 id in TableA
The SQL is as follows
SELECT name
FROM TableA
WHERE id IN (
SELECT up_level_id
FROM Table A
WHERE id IN (
SELECT up_level_id
FROM Table A
WHERE id=5) --query the id:5's top-level name
);
But when I join these two tables as follows, it goes wrong
SELECT sum(amount) AS sum_amount, name AS top_lvl_name
FROM TableA, TableB
WHERE id = org_id
AND id IN (
SELECT up_level_id
FROM TableA
WHERE id IN (
SELECT up_level_id
FROM TableA
WHERE TableA.id IN(
SELECT org_id
FROM TABLEB
)
)
);
I get nothing as above
What can I do to make this query to be correct?
Thanks for everyone's answer and comment.
Finally, I find it very difficult to query the result as I wish. So, I've come up with a shortcut——create a new table that a three-level structure recorded horizontally, which looks like
| lv1_id | lv2_name | lv2_id | lv2_name | lv3_id | lv3_name |
| :------- | :-------: | :------: | :----------:| :------: | :----------:|
| 1 | lv1_name1 | 3 | lv2_name1 | 5 | lv3_name1 |
| 1 | lv1_name1 | 3 | lv2_name1 | 6 | lv3_name2 |
| 2 | lv1_name2 | 4 | lv2_name1 | 7 | lv3_name3 |
| 2 | lv1_name2 | 4 | lv2_name1 | 8 | lv3_name4 |
As above,I can easily connect two tables

All the customers who have spend more than 1200

I need to write a query where on this table
CREATE TABLE sales (
OrderID INT,
OrderDate DATE,
OrderPrice INT,
OrderQuantity INT,
customerName VARCHAR(20)
);
This is my table right now
+---------+------------+------------+---------------+--------------+
| OrderID | OrderDate | OrderPrice | OrderQuantity | customerName |
+---------+------------+------------+---------------+--------------+
| 1 | 2005-12-22 | 160 | 2 | Smith |
| 2 | 2005-08-10 | 190 | 2 | Johason |
| 3 | 2005-07-13 | 500 | 5 | Baldwin |
| 4 | 2005-07-15 | 420 | 2 | Smith |
| 5 | 2005-12-22 | 1000 | 4 | Wood |
| 6 | 2005-10-02 | 820 | 4 | Smith |
| 7 | 2005-11-03 | 2000 | 2 | Baldwin |
+---------+------------+------------+---------------+--------------+
Where I need to get the names of all the unique customers who have spent more than 1200
Use aggregation and having:
select customerName
from sales
group by customerName
having sum(orderPrice) > 1200

mysql query for multiple foreign keys

mysql tables are as follows
+------------+----------------+----------------+
| booking_id | boarding_point | dropping_point |
+------------+----------------+----------------+
| 1 | 2 | 4 |
| 2 | 1 | 2 |
+------------+----------------+----------------+
+-------------+---------------+
| location_id | location_name |
+-------------+---------------+
| 1 | chennai |
| 2 | coimbatore |
| 3 | tiruppur |
| 4 | erode |
| 5 | salem |
+-------------+---------------+
boarding_point and dropping_point are foreign keys for location_id.
Now I want the select query to display like
+------------+----------------+----------------+
| booking_id | boarding_point | dropping_point |
+------------+----------------+----------------+
| 1 | coimbatore | erode |
| 2 | chennai | coimbatore |
+------------+----------------+----------------+
can anyone please suggest me the query to display like above.
Join the booking table twice to the location table:
SELECT
b.booking_id,
t1.location_name,
t2.location_name
FROM booking b
INNER JOIN location t1
ON b.boarding_point = t1.location_id
INNER JOIN location t2
ON b.dropping_point = t2.location_id;
Demo

INNER JOIN in MySQL

There are my two tables:
Table name: FRIENDS
+-------+---------+---------+-------------------+
| id | firstName | lastName | city |
+-------+--------------+------------+-----------+
| 1 | dudi | edri | london |
| 2 | maor | azulay | madrid |
| 3 | batel | azulay | tel aviv |
| 4 | nir | cohen | barcelona |
| 5 | evia | perez | miami |
| 6 | neria | perez | new-york |
| 7 | nevo | kakoun | roma |
+-------+---------+---------+-------------------+
Table name: ORDERS
+-------+---------+---------+-----------------+
| id | firstName | amount | status |
+-------+--------------+----------+-----------+
| 1 | dudi | 5684 | shipped |
| 2 | maor | 4896 | shipped |
| 3 | batel | 2496 | delay |
+-------+--------------+----------+-----------+
my question is:
I want the friends that have no order.
The answer:
| 4 | nir | cohen | barcelona |
| 5 | evia | perez | miami |
| 6 | neria | perez | new-york |
| 7 | nevo | kakoun | roma |
+-------+---------+---------+-------------------+
how i wrote the query with inner join.
Thanks.
You shouldn't use firstName in ORDERS as Foreign Key. The foreign key should reference the primary key. Use ID from FRIENDS like:
Table name: ORDERS
+-------+---------+---------+-----------------+
| id | friendID | amount | status |
+-------+--------------+----------+-----------+
| 1 | 1 | 5684 | shipped |
| 2 | 2 | 4896 | shipped |
| 3 | 3 | 2496 | delay |
+-------+--------------+----------+-----------+
And query using LEFT OUTER JOIN:
SELECT f.*
FROM FRIENDS f
LEFT JOIN ORDERS o
ON f.ID = o.friendID
WHERE o.ID IS NULL;
LiveDemo
Another possibility is to use correlated subquery:
SELECT f.*
FROM FRIENDS f
WHERE NOT EXISTS (SELECT 1
FROM orders o
WHERE o.friendID = f.ID);
LiveDemo2
Tables:
CREATE TABLE friends(
id INTEGER NOT NULL PRIMARY KEY -- you can add AUTO_INCREMENT if needed
...
);
CREATE TABLE orders(
id INTEGER NOT NULL PRIMARY KEY
,friendID INTEGER NOT NULL
,FOREIGN KEY (friendID) REFERENCES friends(id)
...
);

LEFT JOINs with multiple tables

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).