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.
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 am new to SSRS. I have a requirement to display top 3 products based on sales for each country where country is a column grouping, in a tablix.So the report should look like this ( the countries should appear as columns with products and total sales underneath.Unfortunately I am unable to type the below as expected)
UK
Prod1 100
Prod3 70
Prod4 50
Spain
Prod2 80
Prod3 55
Prod4 30
Italy
Prod3 45
Prod1 20
Prod4 15
Top N filter applied at the column group does not work as it seems to be ignoring it completely. Top N cannot be applied at the Table level as it will only display Top 3 across all countries. The data is sourced from a cube.
Any help is much appreciated
This is something you should solve in your select query and that shouldn't be too hard.
I don't know your database layout so I'll try and explain it with a simple example:
Sales Table
SalesId
CustomerId
Date
Total
SalesDetails table
SalesDetailId
SalesId
Product
Quantity
CustomersTable
CustomerId
Country
Name
SELECT DISTINCT(c.Country), q.Product, q.Quantity
FROM Customers c
JOIN (SELECT c1.Country, d1.Product, SUM(d1.Quantity) as Quantity
FROM SalesDetails d1
JOIN Sales s1 ON s1.SalesId = d1.SalesId
JOIN Customer c1 ON c1.CustomerId = s1.CustomerId
GROUP BY d1.Product, c1.Country) q ON q.Country = c.Country
WHERE q.Product IN (SELECT TOP 3 d2.Product
FROM SalesDetails d2
JOIN Sales s2 ON s2.SalesId = d2.SalesId
JOIN Customer c2 ON c2.CustomerId = s2.CustomerId
WHERE c2.Country = c.Contry
GROUP BY d2.Product, c2.Country
ORDER BY SUM(d2.Quantity) DESC)
ORDER BY c.Country
I hope this is of use to you, if you share your actual database layout I'm willing to update my example based on yours.
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.
Please take a look at this fiddle:
I have this query to get the percentage difference of each item's price against the average price of their own category:
SELECT name, product.category, ((price - avg_price)/avg_price)*100 as price_difference
FROM product
JOIN (
SELECT category, AVG(price) as avg_price
FROM product
GROUP BY category
) t
ON t.category = product.category
Now I want to take a step further to add another query to count the number of products in the same category by year
Original table:
ID name category year
1 A Outdoor 2010
2 B Doll 2009
3 C Doll 2009
4 D Outdoor 2010
5 E Brainteaser 2010
6 F Brainteaser 2009
7 G Brainteaser 2009
8 H Brainteaser 2009
The outcome should be like this:
name CATEGORY DIFFERENCE similar_products_of_the_same_year
A Outdoor -72% 2
B Doll 29% 2
C Doll -29% 2
D Outdoor 9% 2
E Brainteaser -88% 1
F Brainteaser 134% 3
G Brainteaser 65% 3
H Brainteaser -47% 3
I can only make a specific query like the following but I need to get the records for each product.
SELECT COUNT(year) AS similar_items_of_the_year from `product` where year in (
SELECT year
FROM product
where name = "A"
)
Would anyone please show me how to get that outcome?
SELECT p.name
, p.year
, p.category
, ((p.price - avg_price)/avg_price)*100 price_difference
, ttl
FROM product p
JOIN
( SELECT category
, AVG(price) avg_price
FROM product
GROUP
BY category
) t
ON t.category = p.category
JOIN
( SELECT category,year, COUNT(*) ttl FROM product GROUP BY category,year ) n
ON n.year = p.year
AND n.category = p.category;
http://sqlfiddle.com/#!2/f182e/14
If my result differs from yours, I think that's because I don't understand whether or not you consider a row as being similar to itself. If you do, just subtract 1 from ttl.
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