Joining 3 Tables on mySQL - php

Good Day.
I know this question is already asked but I have a hard time implementing my problem.
I want to Join 3 tables. Here is how my tables look like:
Order_Header(Order_Header_ID{PK}, Order_Date, Order_Time, Order_Complete)
Order_Line(Order_Line_ID{PK}, Product_ID{FK}, Order_Header_ID{FK},Quantity)
Products(Product_ID{PK}, Description, Cost)
I Want to JOIN the three tables so that in one table it displays Order_Header_ID, Quantity and Description out of the three tables WHERE Order_Complete = 'YES'.
I have the following SQL that displays all the information but do not join them.
SELECT
Order_Header.Order_Header_ID,
Products.Description,
Order_Line.Quantity
FROM Order_Header, Products, Order_Line
WHERE Order_Complete = 'yes'
The idea is that it list a Order_Header_ID once with the corresponding Description and Quantity only once.
Thank you in advance

Your current query is missing join conditions. Also, it is preferable to use an explicit join syntax. Correcting for both of these things we can write the following query:
SELECT
oh.Order_Header_ID,
p.Description,
ol.Quantity
FROM Order_Header oh
INNER JOIN Order_Line ol
ON oh.Order_Header_ID = ol.Order_Header_ID
INNER JOIN Products p
ON ol.Product_ID = p.Product_ID
WHERE
oh.Order_Complete = 'yes'

Related

What is the query to join 4 tables

I'm struggling in joining table.
SELECT ordersId, usersName, productName, price, quantity,total
FROM orders o, users u, products p, orderdetail od
WHERE ....
the tables are
users table:
usersId(pk)|usersName|....
products table:
productId(pk)|productName|price|...
orders table:
ordersId(pk)|date|usersId(fk)
orderdetails table:
ordersId(fk)|productId(fk)|price|quantity|total
the output should be
new table:
ordersId|usersName|productName|price|quantity|total
but the question is... is the output possible to do or not? Because I keep on getting errors if no error no output. Please Help
You need to find common columns among tables, which is how you'll be able to join the data together. The table which contains the majority of the data you want will derive from OrderDetails, so start there and build one join at a time.
SELECT OD.OrdersID, U.UsersName, P.ProductName, OD.Price, OD.Quantity, OD.Total
FROM OrderDetails OD
JOIN Orders O ON O.OrdersID = OD.OrdersID
JOIN Products P ON P. ProductID = OD.ProductID
JOIN Users U ON U.UsersID = O.UsersID
Here is a sample of the working code:
https://dbfiddle.uk/?rdbms=sqlserver_2019&fiddle=9565d9712e7d86b56ddf1656d3b3b914
Please format your question better next time, following the Stack Overflow guidelines for creating tables within questions/answers.

How to join hierarchical table in MySQL (table joins other table that joins other table that joins other table)?

I have 3 tables, tb_item, tb_branch, tb_department, tb_division.
As you can see:
tb_division is under tb_department
tb_department is under branch
tb_branch has no superior
for example if I want to retrieve item_id 1 or 2 or 3 then this should be the result
If I want to retrieve item_id 2 then it will show the department and branch.
My problem is that I can nested join them if if I know the item is related to a specific table but in this case since tb_item can be related to tb_division or tb_department and tb_branch I don't know what query should I formulate.
Changing the database design is not an option since this design is already implemented.
SELECT column-names
FROM table-name1 JOIN table-name2
ON column-name1 = column-name2
WHERE condition
Never Mind guys. I managed to solved it myself. been struggling since I thought I need to do tons of subqueries. Thanks for the answers tho.
SELECT
i.item_id,
dv.division_name,
COALESCE(dept.department_name, dept2.department_name) AS department_name,
COALESCE(br.branch_name, br2.branch_name, br3.branch_name) AS branch_name
FROM
tb_item AS i
LEFT JOIN
tb_division AS dv
ON i.division_id = dv.division_id
LEFT JOIN
tb_department AS dept2
ON dv.department_id = dept2.department_id
LEFT JOIN
tb_branch AS br2
ON dept2.branch_id = br2.branch_id
LEFT JOIN
tb_department AS dept
ON i.department_id = dept.department_id
LEFT JOIN
tb_branch AS br3
ON dept.branch_id = br3.branch_id
LEFT JOIN
tb_branch AS br
ON i.branch_id = br.branch_id

mysql join three tables order by third

I have a query
SELECT jss_products.* from jss_products_tree,jss_products
WHERE stock!=0 AND
jss_products.productID = jss_products_tree.productID
and sectionID=1 order by price
Which returns me a big array with products. Now I need to join 3rd table jss_extrafields_values,
which has productID and content fields, and somehow order the array by the content from 3rd table. Also it might have more than one rows with different content but same product.ID.. any ideas on how to join all of them? I tried a lot of tutorials but none of them helped me.. thanks
Its easier to use join over from table1, table2 as its better to read. And you can just join the 3th table.
SELECT jss_products.* from jss_products_tree
INNER JOIN jss_products
ON jss_products.productID = jss_products_tree.productID
INNER JOIN jss_extrafields_values
on jss_extrafields_values.productId = jss_products.productID
WHERE stock!=0 AND
and sectionID=1
order by jss_extrafields_values.field

Using multiple inner joins

I have four tables:
users, orders, orders_product and products.
They are connected to each other by foreign key
user tables contains: id, name, email and username.
product table contains: id, product_name, product_description and product_price
orders table contains: id, u_id(foreign key).
orders_product table contains: id, product_id(foreign key), order_id(foreign key).
Now I was trying to fetch the name of a user with the total price of a particular order that he has placed.
The maximum I could went for was something like this:
SELECT prod.order_id,
SUM(product_price) AS Total
FROM products
INNER JOIN
(SELECT orders.id AS order_id,
orders_product.product_id
FROM orders
INNER JOIN orders_product ON orders.id = orders_product.order_id
WHERE order_id=1) AS prod ON products.id = prod.product_id;
It showed me total price of a particular order. Now I have two questions:
Is that query correct. It looks like a very long query. Can the same result be achieved with a smaller one?
How to fetch the name of a user with the total price of a particular order that he has placed.
Hi some addition to #Gordon Linoff
your query seems ok.
if you store your price data in order_products it will be good and some benefit, one of these benefit is aggregation will be simple. Second benefit if product price change it will not affect to order.
Your query is correct for one order, but it can be improved:
Don't use a subquery unless necessary. In MySQL this introduces additional overhead.
You are only looking at one order, which seems on the light site. You should remove the where clause.
You should be using a group by because you want aggregation.
You need to join in the user table to get the name.
I also added table aliases (abbreviations for table names). This makes the query a bit more readable:
SELECT u.name, SUM(p.product_price) as Total
FROM orders_product op INNER JOIN
orders o
ON o.id = op.order_id INNER JOIN
products p
ON p.id = op.product_id INNER JOIN
users u
on o.userid = u.id
WHERE op.order_id = 1
GROUP BY u.name;
Your SQL is wrong. Because You want to calculate specific to user. But your SQL is specific to Order. Your SQL will give result for One Order. Please make it User Specific by giving user name or what ever is unique.

MySQL/PHP, getting all the data in one go

I have a database with three tables:
Products
MaterialsProducts
Materials
The relationship between the tables are like this:
Materials 1-* MaterialsProducts *-1 Products
Quite often I need to retrieve 200+ products and their related material data (from the Materials table).
Currently it is done like this:
SQL: select all relevant products
PHP: iterate through the selected products, calling the database to select material data for each product(generating a database call for each product!)
Is there a way to select all relevant products + their material data at the same time? And still have each product only take up one row in the result.
So the solution shouldn't be "SELECT * FROM products p, materialsproducts mp, materials m WHERE p.id = mp.productid AND m.id = mp.materialid WHERE x". (That SELECT would make each product take up more than one row in the result.)
you can use left join to get all data you need
documentation here
Your query have a mistake
"SELECT * FROM `products` p LEFT JOIN `materialsproducts` mp on p.`id` = mp.`productid` LEFT JOIN `materials` m ON m.`id` = mp.`materialid` WHERE $whateveryouneed"
remember to not limit your WHERE to only 1 ID otherwise you will need more queries.
UPDATED
as asked
products has a 1-* relationship with both materialsproducts and typesproducts. materialsproducts has a *-1 relationship with materials. typesproducts has a *-1 relationship with types.
So you can make a left join query as above in this way
SELECT * FROM `products` p
LEFT JOIN `materialsproducts` mp
ON p.`id` = mp.`productid`
LEFT JOIN `materials` m
ON mp.`mp_field_id_here` = m.`m_field_id_here` //here you need to change with actual field to compare
LEFT JOIN `typesproducts` tp
ON p.`id` = tp.`tp_field_id_here` //here you need to change with actual field to compare
LEFT JOIN `types` t
ON tp.`tp_field_id_here` = t.`t_field_id_here` //here you need to change with actual field to compare
then you can add a where statment to limit result to something that suits you
WHERE WHATEVER_YOU_NEED
UPDATED AGAIN
to limit result to only some filed just change * to something specific as
"SELECT p.`Product_Name`, m.`Material_1`, m.`Material_2, m.`Material_3`, t.`Type_1`, t.`Type_2` FROM .....
NOTE I assume you retrieve material 1, material 2, material 3 from material table wich is why i used as prefix m. Either way i used as prefix t for type 1 and type 2 because i thought they are fileds of type table, otherwise you can change them according to your needs.
Try
SELECT p.*, mp.*,m.*
FROM products p
JOIN materials m ON p.id=m.prd_id
JOIN materialsproducts mp ON m.mp_id=mp.id;
It is not simple to have a query like this compress the materials data into a single row for each product - so I don't think that plan will work well for you.
What I would recommend instead is to use a normal JOIN query (much like the one you put in your question and rejected), then use PHP code to deal with the cases where a single product has multiple rows in the result set because it is linked to multiple materials.
You could use GROUP_CONCAT to combine materials related to the same product into a single list while grouping by products:
SELECT
p.ProductID,
p.ProductName,
GROUP_CONCAT(m.MaterialName) AS Materials
FROM Products p
INNER JOIN MaterialsProducts mp ON p.ProductID = mp.ProductID
INNER JOIN Materials m ON m.MaterialID = mp.MaterialID
GROUP BY
p.ProductID,
p.ProductName
;

Categories