I have four tables that I need to pull data from. Three of the tables have a common value (product_id) the fourth table has a value in common with the third table (category_id). So they look something like this:
Products:
product_id, name, quantity, image, weight
Product_Description:
product_id, Description
Product_to_Category:
product_id, category_id
Category:
category_id, category_name
I need to pull all of the data and combine it into a result that looks like this
Name, Quantity, Image, Weight, Description, Category name
I know how to do a JOIN that works for the first three tables but I don't know how to add the into the results.
Just add an additional join on the category_id:
select p.name, p.quantity, p.image, p.weight, pd.description, c.category_name
from products p
join product_description pd on p.product_id = pd.product_id
join Product_to_Category pc on p.product_id = pc.product_id
join category c on pc.category_id = c.category_id
A Visual Explanation of SQL Joins
Related
So I have a task all I need to do is to write Query to
select all the product names and which category they belong to.
I Using the tables from W3SCHOOL - https://www.w3schools.com/sql/trysql.asp?filename=trysql_select_all
I Would like to know why this Query -
SELECT p.ProductName
, c.CategoryName
From Products p
Join Categories c
ON p.ProductID = c.CategoryID
not working for me, it gives me only 8 Products with 8 different category names and I need all of the products name from each category.
thank you.
Your query is almost correct, you are joining on the wrong column,
SELECT Products.ProductName, Categories.CategoryName
FROM Products
JOIN Categories ON Categories.CategoryID = Products.CategoryID
should do.
The issue with your join query
You are joining Products.ProductID when you should join Products.CategoryID
The correct query should be as the following:
SELECT p.ProductName, c.CategoryName
FROM Products p
JOIN Categories c ON p.CategoryID = c.CategoryID
Running the following SELECT query gives unexpectedly two times the same record while there is only 1 product in the database. The are however multiple subcategories linked to the same category, but I still don't understand why this would give two results.
The ERD:
The full contents of the DB:
SELECT p.id AS productId, p.name AS productName FROM product p
INNER JOIN product_base AS pb ON pb.id = p.product_base_id
INNER JOIN product_category AS pc ON pc.id = pb.product_category_id
INNER JOIN product_subcategory AS psc ON psc.product_category_id = pc.id;
Returns:
Why is this product returned two times?
Appending WHERE psc.id = 2 will still give one product as a result, while the intention is that this product should only be found when psc.id = 1.
What am I missing here? Is there something wrong with the structure? How would I get all products that have a certain subcategory?
Would I need to store product_category_id and product_subcategory_id directly in product as well?
#barmar made me realize I am simply missing a direct FK from product to product_subcategory. Otherwise there is of course a missing link between the product and subcategory.
DISTINCT will filter out the duplicates.
SELECT DISTINCT p.id AS productId, p.name AS productName
FROM product p
INNER JOIN product_base AS pb ON pb.id = p.product_base_id
INNER JOIN product_category AS pc ON pc.id = pb.product_category_id
INNER JOIN product_subcategory AS psc ON psc.product_category_id = pc.id;
I have a query that joins 3 tables on product id, here is the code.
SELECT oc_product.product_id, oc_product.image, oc_product.price, oc_product_description.name
FROM oc_product
JOIN oc_product_description
ON oc_product.product_id = oc_product_description.product_id;
I get the product_id, image, price and description, but I need to take the category name too, the product is in a many to many relationships with category table. Looks like this.
[oc_product_to_category * pivot table][1]
And I need to take category name from this table.
[oc_category_description][2]
[1] https://i.stack.imgur.com/5WAKd.png
[2] https://i.stack.imgur.com/YNcLn.png
Thank you so much, I am very stuck with this!
PS: I want to take category name and join with my code with other columns.
You only need to append 2 more JOINs to your query:
Join oc_product → oc_product_to_category to link products with their categories
Then Join oc_product_to_category → oc_category_description to grab the
category details
This way you can include to your query whichever fields you need from any of the joined tables.
SELECT p.product_id, p.image, p.price, d.name, c.name, c.description
FROM oc_product AS p
JOIN oc_product_description AS d
ON p.product_id = d.product_id
JOIN oc_product_to_category AS pc
ON pc.product_id = p.product_id
JOIN oc_category_description AS c
ON c.category_id = pc.category_id;
As you noted, the use of aliases for the actual table names helps to simplify a bit both the SELECT and the JOIN-ON segments of the query.
I've created a quick example here to show the results.
So I have a product/categories/brands structure where a products categories are identified by a column containing a comma separated list of category IDs, i.e. 101,105,108, as well as a brand ID column.
I'm trying to get a list of all the products, replace the category IDs with a comma separated list of category names, and also the brand name.
I have the following query that works:
SELECT
productid AS product_id,
prodname AS name,
prodcode AS code,
proddesc AS description,
prodprice AS price,
GROUP_CONCAT(c.catname)
FROM
products p,
categories c
WHERE
FIND_IN_SET(c.categoryid, p.prodcatids)
GROUP BY p.productid
However when I try and left join as follows to also get the brand name, it breaks and says that column p.prodbrandid doesn't exist (it does).
SELECT
productid AS product_id,
prodname AS name,
prodcode AS code,
proddesc AS description,
prodprice AS price,
b.brandname AS brand,
GROUP_CONCAT(c.catname)
FROM
products p,
categories c
LEFT JOIN
brands b ON p.prodbrandid = b.brandid
WHERE
FIND_IN_SET(c.categoryid, p.prodcatids)
GROUP BY p.productid
Any pointers to what I'm missing would be greatly appreciated!
From the advice in the comments:
SELECT
p.productid AS product_id,
p.prodname AS name,
p.prodcode AS code,
p.proddesc AS description,
p.prodprice AS price,
b.brandname AS brand,
GROUP_CONCAT(c.catname)
FROM
products p
INNER JOIN categories c on FIND_IN_SET(c.categoryid, p.prodcatids) > 0
LEFT JOIN brands b ON p.prodbrandid = b.brandid
GROUP BY p.productid
It's not ideal to store data as comma separated lists though; this really should be split out to an additional table that breaks down the many:many relationship between product and category (multiple products can have multiple categories) into two 1:many relationships (a productcategories table, that has a productid,categoryid pair)
Consider something like this as a one time op:
CREATE TABLE ProductCategories(ProductId INT, CategoryId INT)
INSERT INTO ProductCategories
SELECT
p.productid, c.categoryid
FROM
products p
INNER JOIN categories c on FIND_IN_SET(c.categoryid, p.prodcatids) > 0
Then use it going forwards, and drop the categories column
I have two tables
products
id
code
description
category
subcategory
product_categorys
id
category_name
category_master
Data in products table
1, UK001, Description Text, 1, 2
Data in product_category table
1, Network Cable, 0
2, CAT6, 1
I want to lookup the products and return the category and subcategory i have reserached the best way to do this butt canot get my head around it, i have managed to return one lookup using the following.
SELECT products.product_code, products.description, product_category.category_name, product_category.category_name
FROM products
LEFT JOIN product_category ON product_category.id = products.category AND product_category.ID = products.subcategory
ORDER BY description ASC
Which returns as expected
UK001, Description Text, Network Cables
I also want to return the subcategory, adding another join does not work and this is where i am stuck,
You just need two joins:
SELECT p.product_code, p.description, pc.category_name, pcs.category_name
FROM products p LEFT JOIN
product_category pc
ON pc.id = p.category LEFT JOIN
product_category pcs
ON pcs.ID = p.subcategory
ORDER BY description ASC;
Note also the use of table aliases. These make the query easier to write and to read.