I have 5 tables that need to be joined. These tables have to do with orders placed by customers and the orders turned into purchase orders for the relevant suppliers.
Table product_sale holds the customers products that they've ordered.
Table product holds the main information on those products.
Table sale_purchase is a bridging table between the sale and purchase order.
Note: This may or may not exist as the product might be out of stock and no purchase order was required.
Table product_purchase holds those linked products on the purchase order.
Table grn handles the receiving of those products.
Unfortunately in the customers sales order, I will need to access information from all of these tables. Here's the query I have so far:
SELECT
ps.*,
pp.received_qty,
p.group_ref,
p.subgroup_ref,
g.grn_id AS 'grn_ref',
g.grn_date
FROM
product_sale ps
INNER JOIN product p ON ps.product_ref = p.product_id
LEFT JOIN sale_purchase sp ON ps.sale_ref = sp.sale_ref
LEFT JOIN product_purchase pp ON pp.so_line_no = ps.line_no
LEFT JOIN grn g ON g.grn_id = pp.grn_ref
WHERE
ps.sale_ref = 150002
GROUP BY
line_no
ORDER BY
line_no
So far so good, although the received_qty for one line is wrong:
The first line's received qty should be 7 and not 4. I've checked the grn table and it definitely says 7. Can I please get some help as to where I am going wrong with this query? Also the grn_ref and grn_date should be NULL for line_no 1.00
Scrap it guys. I figured it out. I hadn't accounted for another purchase order that was in the system. Solution to the problem was adding AND pp.purchase_ref = sp.purchase_ref to the left join for product_purchase. See revised code below:
SELECT
ps.*,
pp.received_qty,
p.group_ref,
p.subgroup_ref,
g.grn_id AS 'grn_ref',
g.grn_date
FROM
product_sale ps
INNER JOIN product p ON ps.product_ref = p.product_id
LEFT JOIN sale_purchase sp ON ps.sale_ref = sp.sale_ref
LEFT JOIN product_purchase pp ON pp.so_line_no = ps.line_no AND pp.purchase_ref = sp.purchase_ref
LEFT JOIN grn g ON g.grn_id = pp.grn_ref
WHERE
ps.sale_ref = 150002
GROUP BY
line_no
ORDER BY
line_no
Related
I have a table let's call it products with a list of Manufacturers and Products.
I have a second table let's call it Customer, Orders.
I can do a join to make a list of all the items from each manufacturer the customer ordered doing an Inner Join. Yet trying to do an Inner Join for the items they did not fails.
I tried an Inner Join with 'Orders.Product != Products.Product' but that only works where the Customer has one order. Once there is more than one order I get the same list I would have doing an Inner Join. Any thoughts? I'll try to make a SqlFiddle tonight but was hoping a quick description might help a MySql / Join expert who has done 'NOT Inner Join'before...
It is called an anti join, you can use left join with is null check:
select p.*
from products p
left join orders o on p.Product = o.Product
where o.product is null
I am trying to learn joins with many to many relationships in mysql,
I have four tables:
customers, orders, products, payments
I am trying to get records as:
customer_name, order_status, pay_method, pro_name
the query I use:
SELECT cust_name,order_status,pay_method,pro_name FROM customer
INNER JOIN orders ON customer.cust_id = orders.cust_id
INNER JOIN payments ON payments.order_id = orders.order_id
INNER JOIN products ON products.pro_id = orders.pro_id
I am receiving results as I want with no issue. But this query shows only one product against one order, then I realize I should have another separate table which will hold many products against one order. In this issue I am not able to get desired result
It's not entirely clear what you're asking, but I'm guessing what you're trying to do is create a many to many table that links orders and products? In which case, you can just create a table called "productorders" which will contain an order_id and a pro_id. Then you would modify your query like this:
SELECT cust_name,order_status,pay_method,pro_name FROM customer
INNER JOIN orders ON customer.cust_id = orders.cust_id
INNER JOIN payments ON payments.order_id = orders.order_id
INNER JOIN productorders ON productorders.order_id = orders.order_id
INNER JOIN products ON products.pro_id = productorders.pro_id;
Joining productorders will get all products associated with an order, and then joining products will get the information associated with each product.
What i would like to archieve:
Getting the correct sum of the total amount of the orders that has been cancelled of user id 2002.
Some pre information:
I am having deals which that has its price in deals.price and its id in deals.ID
I then have orders with a foreign key to deals.ID
Running this SQL:
select SUM(deals.price), orders.* from orders
JOIN deals ON deals.ID = orders.deal_id
where orders.user_id = 2002
and orders.cancelled = 1
Works just fine.
Here is where i get stuck:
As an addition to deals, each deals has products with their own prices.
Table is called deal_products, deal_products.price hold the price and deal_products.product_id has the ID of it.
A order is attached to a deal product in another table called order_products, where order_products.product_id = deal_products.product_id
To sum up: I would like to do is including a if inside the above SQL.
If a order has a row in order_products, get the order_products.product_id and find the price in deal_products (price) and use this instead of deals.price when SUM()'ing.
If there is no row it should use deals.price.
How can this be archieved? To first look in another table if there is a entry, and then further look in to a third table and get a value to use?
You can use COALESCE + LEFT JOIN:
select SUM(coalesce(dp.price, d.price)), o.*
from orders o JOIN deals d ON d.ID = o.deal_id
LEFT JOIN order_products op on op.order_id = o.id
LEFT JOIN deal_products dp on op.product_id = dp.product_id
where o.user_id = 2002 and o.cancelled = 1
group by ...;
COALESCE function returns first not null operand
LEFT [OUTER] JOIN = [INNER] JOIN + all rows of the structure on the left side of the LEFT JOIN keyword, which don't match the ON clause in the right structure.
Hey guys I am this close in being able to represent the data that I wish to display
The column in question is a.state_Id.
I understand from the research I have done that the a.State_Id is out of scope. What is the missing piece to my sql statement?
If I take out the a.State_ID = c.State_Id leaving only the b.Product_Id = c.Product_Id then the data is displayed but I need to match against the state and product.
I know i need to add in another join somewhere but im not sure how. If anyone could help me that would be awesome!
SELECT a.state_id,
a.state_name,
a.state_abbreviatedname,
b.product_id,
b.product_name,
c.stateproduct_price
FROM states a,
products b
LEFT OUTER JOIN stateproducts c
ON a.state_id = c.state_id AND b.product_id = c.product_id
Update 1
The states table has been populated and contains the following fields:
State_Id
State_Name
State_AbbreviatedName
The Products table which has been populated to contain the base products. This table has the following fields:
Product_Id
Product_Name
Each state will have the same products however the price for each product changes with each state. This is why i have the StateProducts table. This table is empty and will be populated one by one by an interface I have created. The statesproducts table will have the following fields
State_Id //reference/relational field to be user for comparison
Product_Id //reference/relational field to be user for comparison
StateProduct_Price //new field
so i understand that i will receive NULL values in the price column.
I have been able to return a sort of cartesion product of the States and products table. However I now need to append the price for each combination on the right side of this cartesion table.
bearing in mind that stateproducts table is empty how would i accomplish this?
I guess you have a Many-to-Many relationship in which States can have multiple Products and Products can be on different States. So you need to join States into the mapping table StateProducts so you can be able to get the products on table Products.
SELECT a.State_ID,
a.State_Name,
a.State_AbbreviatedName,
b.Product_Id,
b.Product_Name,
c.StateProduct_Price
FROM States a
INNER JOIN StateProducts c
ON a.State_ID = c.State_Id
INNER JOIN Products b
ON b.Product_Id = c.Product_Id
To further gain more knowledge about joins, kindly visit the link below:
Visual Representation of SQL Joins
UPDATE 1
use CROSS JOIN keyword,
SELECT a.state_id, a.state_name, a.state_abbreviatedname, b.product_id, b.product_name, c.stateproduct_price
FROM states a
CROSS JOIN products b
LEFT OUTER JOIN stateproducts c
ON a.state_id = c.state_id AND
b.product_id = c.product_id
from A to C, C to B.
By doing LEFT JOIN for each, you'll still end up with all possible states regardless of having actual state products.
SELECT
a.State_ID,
a.State_Name,
a.State_AbbreviatedName,
b.Product_Id,
b.Product_Name,
c.Product_Price
FROM
States a
LEFT JOIN StateProducts c
ON a.State_ID = c.State_Id
LEFT JOIN Products b
ON c.Product_Id = b.Product_Id
Try writing the from clause like this:
from StateProducts c join
States a
on c.state_id = c.state_id join
Products b
on c.product_id = b.product_id
For the Cartesian product (that is, to get all examples of states and products):
SELECT s.state_id, s.state_name, s.state_abbreviatedname,
p.product_id, p.product_name,
sp.stateproduct_price
from States s cross join
Products p left outer join
StateProducts sp
on sp.state_id = s.state_id and
sp.product_id = p.product_id
i have 3 tables: products, buyers and ratings.
a buyer can rate i product and this will be saved as a row in ratings (with buyer_id and product_id) and a buyer can mark one product (at most one favorite product per buyer) as favorite (a binary flag in ratings).
i have a report of all buyers and want to add to each row in the report the name of the buyer's favorite product (if he has one), i tried this:
SELECT b.*, p.name
FROM buyers b, products p
LEFT JOIN ratings r
ON r.buyer_id = b.id
and r.product_id = p.id
and r.isFav=1
unfortunately this throws an error (Unknown column 'b.id' in 'on clause'). so i feel that i'm going the wrong way about it.
is there something that can help me accomplish what i need?
Without seeing the any data, one of the big problems is you are mixing JOIN syntax, I might rewrite it this way:
SELECT b.*, p.name
FROM buyers b
LEFT JOIN ratings r
ON b.id = r.buyer_id
LEFT JOIN products p
ON r.product_id = p.id
WHERE r.isFav=1