Join 3 tables with MySQL - mysql

I have the following tables:
Products
prod_id | prod_name | prod_price
Supermarket
supermarket_id | name | address
supermarket_product
supermarket_id | product_id
How can I join those tables to get a table that shows all the information from Products and Supermarket tables in 1 single big table? I am basically trying to have a table only to hold which product belongs to which supermarket based on it.
I tried the following, but it doesn't work:
SELECT prod_name, prod_price, supermarkets.name
FROM products
INNER JOIN supermarkets
ON supermarket_product.supermarket_id = supermarket.supermarket_id;

You need to join products and supermarkets through bridge table supermarket_product:
select p.*, s.*
from products p
inner join supermarket_product sp on sp.product_id = p.prod_id
inner join supermarket s on s.supermarket_id = sp.supermarket_id

You need to also include supermarket_products in the query. You should also use table aliases to simplify your code:
SELECT p.prod_name, p.prod_price, s.name
FROM products p
INNER JOIN supermarket_product sp ON sp.product_id = p.prod_id
INNER JOIN supermarket s on s.supermarket_id = sp.supermarket_id

Related

Mysql joining multiple tables with hierarchical data

I am building a database for an inventory management application and I have to maintain products with multiple hierarchies of category. I have the following database model :
I want to retrieve the products, description, units of measure and the categories, for which I have used the following query :
SELECT P.ID
,P.wrin
,P.description AS productDescription
,CT.pdtCat AS productCategory
,CONCAT(UN.description,' - ',UN2.description,' - ',UN3.description) AS unitDecomposition
FROM product P
-- JOIN to product_category table
JOIN (
SELECT PC3.ID as catID
,CONCAT(PC1.category,' - ',PC2.category,' - ',PC3.category) as pdtCat
FROM product_category AS PC1
LEFT JOIN product_category AS PC2 ON PC2.parentid = PC1.id
LEFT JOIN product_category AS PC3 ON PC3.parentid = PC2.id
WHERE PC1.parentid IS NULL
) CT ON CT.catID = P.categoryId
JOIN unit UN ON P.primaryUOM = UN.ID
JOIN unit UN2 ON P.secondaryUOM = UN2.ID
JOIN unit UN3 ON P.tertiaryUOM = UN3.ID
The output from this query is :
My query is giving the intended results but seems to go sideways if my product doesn't have 3 levels of categories. The product doesn't appear in the results. Please help :)
In your sub-select you are joining from the "top" category to the bottom category and select the id of the bottom one. If there is no level 3 category, there are no results.
Try something like this:
SELECT P.ID
,P.wrin
,P.description AS productDescription
,CT.pdtCat AS productCategory
,CONCAT(UN.description,' - ',UN2.description,' - ',UN3.description) AS unitDecomposition
FROM product P
-- JOIN to product_category table
JOIN (
SELECT PC3.ID as catID
,CONCAT(PC1.category,' - ',COALESCE(PC2.category, ''),' - ',COALESCE(PC3.category, '')) as pdtCat
FROM product_category AS PC3
LEFT JOIN product_category AS PC2 ON PC3.parentid = PC2.id
LEFT JOIN product_category AS PC1 ON PC2.parentid= PC1.id
) CT ON CT.catID = P.categoryId
JOIN unit UN ON P.primaryUOM = UN.ID
JOIN unit UN2 ON P.secondaryUOM = UN2.ID
JOIN unit UN3 ON P.tertiaryUOM = UN3.ID
EDIT:
My query will produce some ' - - category' results for the product category.
Due to the fact that my strength is in MSSQL, that's an exercise for you to make it look more pretty ;)

Pull data from 3 tables

I have 3 tables as follows :
Table 1: Product
id_product [Primary Key],added_time.
Table 2: Category
id_category [Primary Key],Category_name.
Table 3: product_category
id_category,id_product [Both Foreign Keys]
I want to pull Data as
Category_name,No Of Products in this Category,Last time when product was added to Category(Latest product added_time).
You could use this SQL:
SELECT Category.Category_name,
Count(DISTINCT Product.id_product) AS num_products,
Max(Product.added_time) last_added_time
FROM Category
LEFT JOIN product_category
ON product_category.id_category = Category.id_category
LEFT JOIN Product
ON Product.id_product = product_category.id_product
GROUP BY Category.Category_name;
Note that by using LEFT JOIN you will be certain to list all categories even those for which no products exist. If you don't want those, replace both LEFT keywords with INNER.
Note also that in standard SQL you need to GROUP BY any columns you mention in the SELECT list, unless they are aggregated, like with MAX or COUNT.
SELECT C.`Category_name`,
(SUM(IF(P.`id_product`IS NULL,0,1))) AS No_of_Products,
MAX(P.`added_time`) AS Latest_time
FROM
Category C
LEFT JOIN
product_category P_C ON C.`id_category` = P_C.`id_category`
LEFT JOIN
Product P ON P.`id_product` = P_C.`id_product`
GROUP BY C.`id_category`
Hope this helps.

Joining 4 tables related

I'm trying to join these 4 tables:
customers:
id_customer;
name;
surname
employers:
id_employer;
id_customer;
products_to_employer
id_product;
id_employer;
products
id_product;
name_product;
code;
price;
Where i basically try to get all products of a customer. Basically each product is related whit a id_employer, but each employer is related whit a customer, so what i want is to bring all the products that is not related whit the employer but whit his "parent" the customer.
The result I want to get is:
Result:
Example: variable $id_customer: 4
products result:
id_customer (id nr 4)
name_product;
name_product;
code;
price;
This is the requirement:
Where i basically try to get all products of a customer
So it is just a matter of applying some joins and a where clause for the filter on id_customer
select p.* from products p
join products_to_employer pe on p.id_product = pe.id_product
join employers e on pe.id_employer = e.id_employer
join customers c on e.id_customer = c.id_customer
where c.id_customer = 4
NOTE: There shouldn't be any need of adding the id_customer to the results as you are already filtering by it.
select c.id_customer, c.name, p.name_product, p.code, p.price
from products p
inner join products_to_employer pte on (pte.id_product = p.id_product)
inner join employers e on (e.id_employer = pte.id_employer)
inner join customers c on (c.id_customer = e.id_customer)
where c.id_customer = 4

MySQL COUNT() with multiple joins

I am building a course system, with courses, instructors and a table to relate the two.
Symplified table instructors:
id | name | ...
Symplified table courses:
id | name | instructors_needed | ...
Symplified table link:
id | course_id | instructor_id
I created the following query to fetch the names of the instructors associated to a particular course:
SELECT i.name, c.name, c.instructors_needed FROM courses c
LEFT OUTER JOIN
link
ON c.id = link.course_id
LEFT OUTER JOIN
instructors i
ON link.instructor_id = i.id
This works fine. I created the following query to find the number of instructors on each course:
SELECT COUNT(i.name) as number, c.id, c.name, c.instructors_needed FROM courses c
LEFT OUTER JOIN
link
ON c.id = link.course_id
LEFT OUTER JOIN
instructors i
ON link.instructor_id = i.id
GROUP BY c.ID
I want to combine the two queries, to get all details about the instructors for a particular case, but also the total number of instructors on the course and the number of instructors needed. How do I do that? I understand that the GROUP BY is the problem here.
I searched but I could only find examples with 2 tables instead of 3, and I somehow can't figure it out for three tables.
Your help is really appreciated, thank you!
Try:
SELECT i.name, c.name, c.instructors_needed, Ctr.CourseCount FROM courses c
LEFT OUTER JOIN
link
ON c.id = link.course_id
LEFT OUTER JOIN
instructors i
ON link.instructor_id = i.id
LEFT OUTER JOIN
(SELECT link.course_id, COUNT(*) as CourseCount FROM link GROUP BY link.course_id) Ctr
ON link.course_id = Ctr.course_id

Select only rows where count of rows in other table is greather than 0

I have 2 tables in my database:
Products:
--------------------------------------------------
| id | product_name | manufacturer |
--------------------------------------------------
Products_photos:
-----------------------------------------------
| id | product_id | image_name |
-----------------------------------------------
I want select all Products, where Product_photos count is greater than 0.
How I can do that?
#Edit:
I don't want to add results from Products_photos for my output. I want only show entries from Products, where are any images. Sorry for my english :)
Thanks for help
I think the joining solutions already offered are the best bet, in terms of query efficiency. But for clarity - in terms of expressing exactly what you ask for - I would choose an approach like this:
select * from products p
where exists (select * from products_photos pp where pp.product_id = p.id)
SELECT p.id, p.product_name, p.manufacturer
FROM Products p
INNER JOIN Products_photos i on i.product_id = p.id
you can do
Select P.id, P.product_name, P.manufacturer
from Products P
INNER JOIN Products_photos Pp on P.Id = Pp.product_id
For the Inner Join, it will only return rows where it's posible the joining, which means that you have at least one value in the Products_photos table.
SELECT P.* FROM Products AS P INNER JOIN Products_Photos AS PP ON P.id=PP.id
Another method, more inefficient but maybe better for you to understand, would be
SELECT P.* FROM Products AS P
WHERE P.id IN (SELECT DISTINCT id FROM Product_photos)