I have the following query
SELECT
price
FROM prices
left join suppliers s on prices.id_supplier = s.id_supplier
AND prices.id_product = 57;
Table structures are as follows:
Suppliers:
id_supplier
name
1
Supplier 1
2
Supplier 2
3
Supplier 3
Prices
id_pk
id_product
date
price
id_supplier
1
57
2022-12-29
4.99
1
2
57
2022-12-29
6.99
2
So based on the data above, I wish to create a query which fetches all prices for all supplier for a given product, even for Supplier 3 (which we do not have a price for in which case it should return 0)
Outpout I require is as follows:
id_supplier
price
1
4.99
2
6.99
3
0
Is this possible?
You have the tables joined in the wrong order.
You want all rows from supplier, so that's the LEFT table.
SELECT
s.*,
COALESCE(p.price, 0)
FROM
suppliers s
LEFT JOIN
prices p
ON p.id_supplier = s.id_supplier
AND p.id_product = 57
SELECT
CASE WHEN price = 57 THEN 57
WHEN s.id_supplier IS NULL THEN 0
END AS price
FROM prices
LEFT JOIN suppliers s on prices.id_supplier = s.id_supplier
If I am understanding your problem correctly then this should work. Using case statement will get you price as 57 when price is 57 and when id_supplier IS NULL it will assign 0 to that row. Let me know if this helps.
Edit:
SELECT
s.id_supplier,
CASE WHEN price = 57 THEN 57
WHEN price IS NULL THEN 0
END AS price
FROM prices
RIGHT JOIN suppliers s on prices.id_supplier = s.id_supplier
This query will select all the suppliers where price is either 57 or null.
Related
I have to build and SQL query which must do these things:
select all products from table "products" - satisfied
SUM all sales and forecast to the next 3 months - satisfied
check if the product has no one sale, then write "0" -> here is the problem, because I don't know how to do that..
My SQL query is here..
select product.name,
(select sum(amount)
from forecast
where forecast.product_id = product.id),
sum(sale.amount)
from product join
sale
on sale.product_id = product.id
where sale.outlook > -4
group by product.id
Here is the products table:
id name
1 milk
2 roll
3 ham
Table sale (same structure like forecast):
product_id outlook amount
1 -1 9
1 -2 13
1 -3 14
2 -1 88
2 -3 61
3 -1 33
3 -4 16
You can use left join to bring in the rows and coalesce() to get the 0 instead of NULL:
select p.name,
(select sum(f.amount)
from forecast f
where v.product_id = p.id),
coalesce(sum(s.amount), 0)
from product p left join
sale s
on sale.product_id = product.id and
sale.outlook > -4
group by p.id
Understand the requirement to be, show the sales per product and if no sale for a product show "0". Tables are named Products and Sale.
For this, "with" statements are useful and help understanding too:
With SalesSummary as
(
select product_id, sum(amount) as ProductSales
from Sale
Group by product_id
)
select a.ProductID, ISNULL(b.ProductSales,0) as Sales
from products a left join SalesSummary b on a.product_id=b.product_id
I have 2 tables, cart and product. User can choose product from product table and then its details are added to cart table. i wanted a listing that combines the values of these two tables and gives a result
prodsize
id catid catname productid prodsize cost prodname
1 2 CN1 13 small 130 P1
2 2 CN1 13 large 200 P1
3 2 CN1 14 small 50 P2
4 2 CN1 14 medium 90 P2
5 2 CN1 14 large 110 P2
6 2 CN1 12 small 70 P3
7 2 CN1 12 medium 110 P3
8 2 CN1 13 medium 200 P1
cart
id catid catname userid productid prodname prodsize prodcost quantity status
1 2 CN1 1 13 P1 small 130 2 add_to_cart
1 2 CN1 1 13 P1 large 200 2 order_placed
when i run the following query combined value from both the table but here i want that only those products quantity should get displayed whose status is add_to_cart, if the status is order_placed then the quantity should be 0, can anyone plz tell how can i modify the below code to get desired result
$sql= "SELECT p.catid, p.catname, p.productid, p.prodimg, GROUP_CONCAT(p.prodsize ORDER BY p.id ASC) as size, GROUP_CONCAT(p.cost ORDER BY p.id ASC) as cost, p.prodname,
GROUP_CONCAT(c.prodsize,'-',c.quantity) as cart_details, GROUP_CONCAT(DISTINCT(c.userid)) as user_id
FROM productsize p
LEFT JOIN cart c ON(c.productid = p.productid AND c.userid = '$userid' AND p.prodsize = c.prodsize)
WHERE p.catid ='$catid'
GROUP BY p.productid
ORDER BY user_id DESC, p.productid ASC";
I'm a little confused about your two conditions ("ordered" items shouldn't get displayed, and should have quantity 0). If they have a quantity 0, they need to be displayed, right? Anyhow, here's my fix considering you may want to do the latter (get "ordered" items in your query result with a quantity of 0)
You need to group by productid AND status
You need a quantity as an aggregate SUM that takes the status into account
Cleaned up some other things too (e.g. quoted indexes, which will harm performance):
$sql = "SELECT p.catid, p.catname, p.productid, p.prodimg,
GROUP_CONCAT(p.prodsize ORDER BY p.id ASC) as size,
GROUP_CONCAT(p.cost ORDER BY p.id ASC) as cost, p.prodname,
GROUP_CONCAT(c.prodsize,'-',c.quantity) as cart_details,
GROUP_CONCAT(DISTINCT(c.userid)) as user_id,
SUM(CASE WHEN c.status = 'add_to_cart' THEN quantity ELSE 0 END) AS quantity
FROM productsize p
LEFT JOIN cart c ON(c.productid = p.productid
AND p.prodsize = c.prodsize)
AND c.userid = {$userid}
WHERE p.catid = {$catid}
GROUP BY p.productid, c.status
ORDER BY p.productid ASC";
You've already got the where clause. Try adding
AND status = 'add_to_cart'
just after the existing where clause.
Change c.quantity to:
case c.status
when 'add_to_cart' then c.quantity
else 0
end
Since you used a left join, the zero result will also apply when that product didn't appear in the user's cart.
And note that the sort on userid may be effectively ordering the cart and non-cart products but that is the wrong way to express that intention. It's also best to aggregate the non-group columns everywhere.
I have 3 tables. A table for product prices, invoiced products, and ordered products. I am trying to create a view that joins these. I want to output the product prices with a total of invoiced products and a total of ordered products.
products_price
id season_id product_id product_price
1 1 1 3.99
2 1 2 6.99
3 1 3 5.99
4 1 4 5.99
....
invoices_products
id season_id invoice_id product_id piece_qty
1 1 1 1 1600
2 1 2 2 3200
3 1 3 2 200
4 1 4 1 120
....
orders_products
id season_id order_id product_id piece_qty
1 1 1 1 160
2 1 2 1 40
3 1 2 2 20
4 1 3 2 10
....
Here are a few queries from the View statements I've tried so far.
This query gives me everything I want. The View's output is perfect but the SUM() for the first 2 rows is off. total_invoice_product is double for row 1 and 2. total_order_productis 4x for row 1 and 3x for row 2.
Statement 1:
SELECT
`t1`.`id` AS `id`,
`t1`.`season_id` AS `season_id`,
`t1`.`product_id` AS `product_id`,
`t1`.`product_piece_price` AS `product_piece_price`,
SUM(`t2`.`piece_qty`) AS `total_invoice_product`,
SUM(`t3`.`piece_qty`) AS `total_order_product`
FROM
((`products_price` `t1`
LEFT JOIN `invoices_products` `t2` ON (((`t2`.`product_id` = `t1`.`product_id`)
AND (`t2`.`season_id` = `t1`.`season_id`))))
LEFT JOIN `orders_products` `t3` ON (((`t3`.`product_id` = `t1`.`product_id`)
AND (`t3`.`season_id` = `t1`.`season_id`))))
GROUP BY `t1`.`season_id` , `t1`.`product_id`
This query gives me the output that I expect. Its not the full output I want but its correct for the statement. The SUM() totals are off on this one as well.
Statement 2:
SELECT
`t1`.`id` AS `id`,
`t1`.`season_id` AS `season_id`,
`t1`.`product_id` AS `product_id`,
`t1`.`product_price` AS `product_price`,
SUM(`t2`.`piece_qty`) AS `total_invoice_product`,
SUM(`t3`.`piece_qty`) AS `total_order_product`
FROM
((`products_price` `t1`
LEFT JOIN `invoices_products` `t2` ON ((`t2`.`product_id` = `t1`.`product_id`)))
LEFT JOIN `orders_products` `t3` ON ((`t3`.`product_id` = `t1`.`product_id`)))
WHERE
((`t2`.`season_id` = `t1`.`season_id`)
AND (`t2`.`product_id` = `t1`.`product_id`))
GROUP BY `t1`.`season_id` , `t1`.`product_id`
the output I want
id season_id product_id product_price total_invoice total_order
1 1 1 3.99 1720 200
2 1 2 6.99 3400 30
3 1 3 5.99 576
4 1 4 5.99 800
output received for statement 1
id season_id product_id product_price total_invoice total_order
1 1 1 3.99 3440 800
2 1 2 6.99 6800 90
3 1 3 5.99 576
4 1 4 5.99 800
output received for statement 2
id season_id product_id product_price total_invoice total_order
1 1 1 3.99 3440 800
2 1 2 6.99 6800 90
I can build a query like below and it works perfect. I get the exact output I need but this code does not work as a view. I get this error: ERROR 1349: View's SELECT contains a subquery in the FROM clause SQL Statement
Perfect Query but will not work as a view
SELECT
products_price.id,
products_price.season_id,
products_price.product_id,
products_price.product_price,
invoices_grouped.total_invoice_product,
orders_grouped.total_order_product
FROM
products_price
LEFT JOIN
(SELECT
invoices_products.product_id,
invoices_products.season_id,
SUM(invoices_products.piece_qty) AS total_invoice_product
FROM
invoices_products
GROUP BY
invoices_products.product_id) AS invoices_grouped
ON
invoices_grouped.product_id = products_price.product_id
AND
invoices_grouped.season_id = products_price.season_id
LEFT JOIN
(SELECT
orders_products.product_id,
orders_products.season_id,
SUM(orders_products.piece_qty) AS total_order_product
FROM
orders_products
GROUP BY
orders_products.product_id) AS orders_grouped
ON
orders_grouped.product_id = products_price.product_id
AND
orders_grouped.season_id = products_price.season_id
What I need
I've tried several other statements. They either got worse results or the same. Can someone help me get Statement 1 working with a proper SUM?
Edit 1 for a question
The information that this view provides will be called upon a lot. The products_price and invcoices_products tables will not be changed that often. orders_products will be changed a lot. If 2 views are required, would it be more efficient to use the "Perfect" query above or use 2 views?
Edit 2 for another query
Here is another query from my view statement. This query is part of Statement 1 shown above. This query works perfect but it is not complete. I need the second SUM column. When you add the second LEFT JOIN it breaks the SUM totals.
SELECT
`t1`.`id` AS `id`,
`t1`.`season_id` AS `season_id`,
`t1`.`product_id` AS `product_id`,
`t1`.`product_piece_price` AS `product_piece_price`,
SUM(`t2`.`piece_qty`) AS `total_invoice_product`
FROM
(`products_price` `t1`
LEFT JOIN `invoices_products` `t2` ON (((`t2`.`product_id` = `t1`.`product_id`)
AND (`t2`.`season_id` = `t1`.`season_id`))))
GROUP BY `t1`.`season_id` , `t1`.`product_id`
output
id season_id product_id product_price total_invoice
1 1 1 3.99 1720
2 1 2 6.99 3400
3 1 3 5.99 576
4 1 4 5.99 800
Well, MySql has some limitations, so you will need to create 2 views for subqueries and use them:
create view viewInvoices
as
select season_id, product_id, sum(piece_qty) pq
from invoices_products group by season_id, product_id
create view viewOrders
as
select season_id, product_id, sum(piece_qty) pq
from orders_products group by season_id, product_id
select pp.id,
pp.season_id,
pp.product_id,
pp.product_price,
i.pq as total_invoice,
o.pq as total_order
from products_price pp
left join viewInvoices as i
on pp.season_id = i.season_id and pp.product_id = i.product_id
left join viewOrders as o
on pp.season_id = o.season_id and pp.product_id = o.product_id
Try this query
SELECT * from products_price as a left join (select product_id, sum(piece_qty)total_invoices from invoices_products group by product_id) as b on a.product_id=b.product_id left join (select product_id, sum(piece_qty) as total_order from orders_products group by product_id) as c on a.product_id=c.product_id
My project is about a jewelery store and i try to find the profit of each product-category.
Let me be more specific
I have 3 tables which gives me the info:
SALES(salesid,productid,quantity,price)
salesid productid Quantity Price
11001 13001 4 5
11002 13002 6 10
11003 13003 5 16
.
.
11012 13012 7 15
RETURN(salesid,productid,date,quantity,price)
salesid productid Quantity Price
11003 13003 1 16
11007 13007 3 12
11008 13008 3 8
PROCUREMENT(procurementid,productid,quantity,price)
procurementid productid Quantity Price
100001 13001 10 2
100002 13002 10 2
.
.
100012 13012 10 2
product_category(categoryid,category)
categoryid category
1 Gold
2 Silver
.
5 Platin
product(Productid,categoryid)
Productid categoryid
13001 1
13002 3
.
.
13010 5
The profit is given from this type:
Profit=Quantity*Price(Sell)-Quantity*Price(Return)-Quantity*Price(Procurement)
And now here is the problem.. I came up to this so far
SELECT categoryid,
category,
(coalesce(a.rev,0)- coalesce(b.ret,0),
coalesce(c.cost,0)) AS profit
FROM product category AS g
JOIN product AS h ON g.categoryid = h.categoryid
JOIN
(SELECT categoryid,
sum(quantity*price) AS rev
FROM sales AS a,
product AS b
WHERE a.productid = b.productid
GROUP BY categoryid) a
LEFT OUTER JOIN
(SELECT cartegoryid,
sum(quantity*price) AS ret
FROM RETURN AS a ,
product AS b
WHERE a.productid = b.productid
GROUP BY categoryid) b ON a.categoryid = b.categoryid
LEFT OUTER JOIN
(SELECT categoryid,
sum(quantity*price) AS cost
FROM procurement AS a,
product AS b
WHERE a.productid = b.productid
GROUP BY categoryid) c ON a.categoryid = c.categoryid ,
product AS d,
procurement AS e
WHERE MONTH(f.date) = MONTH(e.date)
AND YEAR(date) = 2013
[sorry for the align i am new to the site dont know how to copy paste code well(:D)]
wahtever when i do this it comes to a state like
categoryid category profit
1 Gold -100
2 Silver -100
.
5 Platin -100
dont know where is the problem...i made a lot of changes and switches but nothing came up...any suggestion would be so helpfull.Thank u in advane
Initially looks like your profit formula has an extra comma in it.
this
(coalesce(a.rev,0) - coalesce(b.ret,0),coalesce(c.cost,0)) as profit
should be this
coalesce(a.rev,0) - coalesce(b.ret,0) - coalesce(c.cost,0) AS profit
Few more issues with this query
Right before the where clause, after you join the cost subquery, you add product and procurement tables but don't join them. This will cause a cartesian join which will throw off your results.
In the where clause you don't specify which tables date field you want to use. AND YEAR(date) = 2013 should be e.date or f.date. That should have given you an error if you tried to run it.
WHERE MONTH(f.date) = MONTH(e.date) which table is f.date referring to? You didn't give an alias of f to any table.
You join in procurement and use its date field to filter results by month, but none of your revenue, returns, and cost subquery totals take dates into account. This will throw off your results.
I’m new to mySQL and I’m struggling to write a query that will list all stores where a price for a product has been scanned as well as the stores where it has not been scanned. The following gives the correct result for a single product:
select distinct(s.id) as store_id, s.chainID as chain_id, p1.productID as product_id,
s.chain, s.location, s.city, prd.brand, prd.product, prd.quantity, prd.size, prd.unit
from analytics.price p1 -- Fact table with prices
join analytics.pricetime pt -- Dimension table with time a price was scanned
on p1.priceTimeID = pt.id
join analytics.product prd -- Dimension table with products
on p1.productID = prd.id
and prd.published = 1
right join analytics.store s -- Dimension table with stores and the chain they belong to
on p1.storeID = s.id
and p1.chainID = s.chainID
and p1.productID = 46720
and p1.priceTimeID between 2252 and 2265
where s.published=1
and s.chainID = 5;
When I remove the p1.productID = 46720 clause to get results for all products, I get all the stores that have scanned prices (correct), but the no price side of the right join only shows stores that have not had any prices scanned for any products. (This is a simple star schema with a price fact and dimensions of product, time and store). I would greatly appreciate help – I’ve tried this every way I can think of including “in”, “not exists” and stored procedure with cursor but I seem to hit a brick wall each way I try it.
Edited to clarify:
Here's what I'm trying to achieve:
Price table
Product Chain Store Price
100 5 1 $10
101 5 2 $20
Store table
Chain Store
5 1
5 2
5 3
Desired Result
Product Chain Store Price
100 5 1 $10
100 5 2 NULL
100 5 3 NULL
101 5 1 NULL
101 5 2 $20
101 5 3 NULL
Actual Result
Product Chain Store Price
100 5 1 $10
101 5 2 $20
NULL 5 3 NULL
I prefer the readability of using a LEFT JOIN -- this should return all published stores in chainid 5 and the associated products (given the criteria).
select distinct s.id as store_id, s.chainID as chain_id, s.chain, s.location, s.city,
prd.id as product_id, prd.brand, prd.product, prd.quantity, prd.size, prd.unit
from analytics.store s
left join analytics.price p1
on p1.storeID = s.id
and p1.chainID = s.chainID
and p1.priceTimeID between 2252 and 2265
left join analytics.product prd
on p1.productID = prd.id
and prd.published = 1
left join analytics.pricetime pt
on p1.priceTimeID = pt.id
where s.published=1
and s.chainID=5;
EDIT -- Give comments, it looks like you're looking for a Cartesian Product:
SELECT P.Product, P.Chain, S.Store, IF(P.Store=S.Store,P.Price,NULL) Price
FROM Price P, Store S
WHERE P.Chain = 5
AND S.Chain = P.Chain
ORDER BY P.Product, S.Store
SQL Fiddle Demo