What is the query to join 4 tables - php

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.

Related

Joining 3 Tables on mySQL

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'

DQL\SQL query in Symfony2. Many tables

I have a question about DQL query.
I have these tables: 'orders', 'orders_kitchen', 'orders_institution' and 'variants'.
From the table 'variants', I get order IDs that have already been made offers.
$orders = $em->createQuery("SELECT o
FROM AppBundle:Orders o
JOIN AppBundle:OrdersInstitution oi
WHERE oi.idInstittuion = :institution AND o.idorder = oi.idOrder AND o.finalDeal IS NULL
ORDER BY o.idorder DESC")
->setParameter("institution",$institution)->getResult();
When a customer leaves the order, he may proceed in three ways:
Do not add a record to the table 'orders_institution' some institutions going and add an entry in the table of certain types of cuisines id
Does not add an entry in any of the tables
Add an entry in the table 'orders_kitchen', some types of cuisines ID works with this institution
I need to find all orders that have not selected any one institution, and none of the types of cuisines, or at least one of the kitchen works with the institution (this can be an array).
And I don't want to choose orders whose ID is in the table 'variants'.
You can try it with SQL something like (DQL doesnt performe well with lot of joins) :
$sql = 'SELECT * FROM Orders o JOIN
(SELECT o1.id FROM Orders o1 WHERE o1.cuisine IS NULL OR o1.institution IS NULL) o1 JOIN
(SELECT * FROM Orders o2 INNER JOIN Cuisine c ON c.insitution_id = '.$institution_id.') o2 JOIN (your query);';
Something like this should do it, not expert in SQL i usually end up trying until i get it !
I dont think its correct tho but at least its a start :p

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 returning same data different rows

I am trying to get data from reviews table then, join the same table again but find different data (likes) based on the id of the first table (reviews) and find the corresponding description from yet another joined table (descriptions).
I know this might be hard to visualize but maybe someone will know why the likes from the second reviews table return the same data for different rows:
SELECT r.title, co.likes, d.description
FROM reviews r
INNER JOIN reviews co
INNER JOIN reviews_descriptions d
ON co.id = d.review_id
WHERE co.parent = 52
AND r.id = 52;
The result is two rows in which title and likes have the same data while the description field grabs different data (the correct way). Likes should have different data for each row.
Help please.
An alternative for writing this and I believe this is what you are looking for:
SELECT r.title, co.likes, d.description
FROM reviews r, reviews co, review_descriptions d
WHERE co.parent = r.id AND d.review_id = co.id AND r.id = 52;
Since you are matching co.parent to 52 and r.id to 52, then you should have a join on co.parent = r.id, however, you should rarely have to do a join on the same table. I think your tables are poorly formatted or you don't need to do the join in the first place and should be able to use r.likes instead of co.likes.

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