I have the following tables:
Orders (OID, Count, ProductID, TableNr)
Table (TableNr, Name, Number)
Products (ProductID, Prize)
Now I want to calculate how much was earned per table. I think to do this I have to Group By Orders.TableNr. But how can I multiply the Products.Prize with the Orders.Count and after that sum up this results within the group?
You are describing a join and aggregation:
select o.tableNr, sum(o.count * p.prize) totalEarned
from orders o
inner join products p on p.productId = o.productId
group by o.tableNr
If you want to display table information as well (say, the table name), then you can add another join:
select t.tableNr, t.name, sum(o.count * p.prize) totalEarned
from table t
inner join orders o on o.tableNr = t.tableNr
inner join products p on p.productId = o.productId
group by t.tableNr, t.name
Note that table is a SQL keyword, hence not a good choice for a table name.
Related
I need to create a function which will return the total of an order. I've been given three tables with the following variables
Table 1 - Order
Order_ID
Date_Placed
Date_Fulfilled
Table 2 - Order Product
Order_ID
Product_ID
Product_Quantity
Table 3 - Product
Product_ID
Price
I'm struggling to put together a coherent function. Any help would be greatly appreciated.
I've already attempted to set up the function with joins between both tables, but am unable to figure out where I should be putting my equation.
BEGIN
SELECT order.order_id, SUM(product.price * order_item.quantity)
FROM `order`
JOIN `order_item` ON order.order_id = order_product.order_id
JOIN `product` ON order_product.product_id = product.product_id;
END $$
You might be surprised, but the orders table is not needed for this query. You can just aggregate off the other two tables:
SELECT oi.order_id, SUM(p.price * oi.quantity)
FROM order_item oi JOIN
product p
ON po.product_id = p.product_id
GROUP BY oi.order_id;
You'll need to take your select statement, and group it by your order.order_id. That way you'll have one row per order, with the sum total of that order.
SELECT order.order_id, SUM(product.price * order_item.quantity) as total_price
FROM `order`
JOIN `order_item` ON order.order_id = order_product.order_id
JOIN `product` ON order_product.product_id = product.product_id
GROUP BY order.order_id
this will work:
SELECT order.order_id, SUM(product.price * order_item.quantity)
FROM order o,
JOIN order_item oi,
JOIN product p where
o.order_id = oi.order_id and
oi.product_id = p.product_id
group by order_product.product_id = product.product_id;
I have the tables products and history and I need to group by name:
products = (id_product, name)
history = (id_history, id_product, amount)
I tried this SQL query but it isn't grouped by name:
SELECT
products.name,
sum(history.amount)
FROM history
INNER JOIN products ON history.id_product = products.id_product
GROUP BY
products.name,
history.amount,
history.id_history;
This is the result:
You should only be grouping by the attributes you need to be aggregated. In this case, you need only products.name.
SELECT
products.name,
sum(history.amount) AS [Amount]
FROM history
INNER JOIN products ON history.id_product = products.id_product
GROUP BY
products.name;
If you need to include products without history (assuming sum should be 0 instead of null in this case), then you can use an OUTER JOIN instead of INNER JOIN to include all products:
SELECT
products.name,
COALESCE(sum(history.amount), 0) AS [Amount]
FROM history
RIGHT OUTER JOIN products ON history.id_product = products.id_product
GROUP BY
products.name;
This is no answer, but too long for a comment.
For readability's sake the product table should be first. After all it is products that we select from, plus a history sum that we can access via [left] join history ... followed by an aggregation, or [left] join (<history aggregation query>), or a subselect in the select clause.
Another step to enhance readability is the use of alias names.
Join the table, then aggregate
select p.name, coalesce(sum(h.amount), 0) as total
from products p
left join history h on h.id_product = p.id_product
group by p.name
order by p.name;
Aggregate, then join
select p.name, coalesce(h.sum_amount, 0) as total
from products p
left join
(
select sum(h.amount) as sum_amount
from history
group by id_product
) h on h.id_product = p.id_product
order by p.name;
Get the sum in the select clause
select
name,
(select sum(amount) from history h where h.id_product = p.id_product) as total
from products p
order by p.name;
And as you were confused on how to use GROUP BY, here is an explanation: GROUP BY ___ means you want one result row per ___. In your original query you had GROUP BY products.name, history.amount, history.id_history saying you wanted one result row per name, amount, and id, while you actually wanted one row per name only, i.e. GROUP BY products.name.
I have a table for "branches", "orders" and "products. Each order and product are connected to a branch with branch_id. I need an sql statement to get a list of all branches with a field for how many orders and a field for how many products.
This works:
SELECT b.*, COUNT(o.id) AS orderCount FROM branches b
LEFT JOIN orders o ON (o.branch_id = b.id) GROUP BY b.id
but it only gets the amount of orders, not products.
If I change it to add amount of products, the amounts are wrong because it's getting amount of orders * amount of products.
How can I get the amount of both the orders and the products in the same SQL statement?
Something like this should work (on sql server at least - you didn't specify your engine).
SELECT
b.id
,COUNT(distinct o.id) AS orderCount
,COUNT(distinct p.id) AS productCount
FROM branches b
LEFT JOIN orders o
ON (o.branch_id = b.id)
left join products p
on p.product_id=b.id)
GROUP BY
b.id
Please try:
select
*,
(select COUNT(*) from Orders o where o.branch_id=b.id) OrderCount,
(select COUNT(*) from Products p where o.branch_id=p.id) ProductCount
From
branches b
I've been trying to set up this query.
SELECT P.ProductNo,P.Description, AVG(OrderLine.ActualPrice)
FROM Product P
INNER JOIN OrderLine
ON OrderLine.ProductNo = P.ProductNo
WHERE AVG(ActualPrice) >
(SELECT AVG(ActualPrice)
FROM OrderLine)
My goal here is to compare the average actual price for a product to the average price of all products together. But I don't seem to be getting it to work. Where am I going wrong here?
use GROUP BY
when using aggregated condition, use HAVING instead of WHERE
query,
SELECT P.ProductNo, P.Description, AVG(OrderLine.ActualPrice)
FROM Product P
INNER JOIN OrderLine
ON OrderLine.ProductNo = P.ProductNo
GROUP BY P.ProductNo, P.Description
HAVING AVG(ActualPrice) > (SELECT AVG(ActualPrice) FROM OrderLine)
I have a table Orders with (id,orderCode,productId,quantity,color,size)
where I can have entries like:
1,O20100812,163,2,BLUE,Medium
1,O20100812,163,3,BLUE,Larger
1,O20100812,145,4,RED,Large etc
1,O20100815,134,5,RED,Large etc
1,O20100815,143,2,BLACK,Large etc
1,O20100815,112,8,BLACK,Large etc
And another table Products with (id,name,price)
What I want is to find the total price of all the products in the order with orderCode 020100812. Should I DISTINCT select the order code and then SUM the quantity while JOINing the products table?
Why you need distinct?
Select SUM(o.Quantity * Price) TotalPrice
FROM Orders o JOIN Products p ON (o.ProductId = p.Id)
WHERE OrderCode = '020100812'
For all orders you can use the following query:
Select OrderCode, SUM(o.Quantity * Price) TotalPrice
FROM Orders o JOIN Products p ON (o.ProductId = p.Id)
Group by OrderCode
No, GROUP BY and then you can use SUM to aggregate across the group, e.g.
select O.id, O.ordercode, sum(P.price * O.quantity) as total
from orders O
join products P on P.id = O.productid
group by O.id, O.ordercode
which will show you the total price for each order code within each order - if you wanted all order codes across all orders you'd need
select O.ordercode, sum(P.price * O.quantity) as total
from orders O
join products P on P.id = O.productid
group by O.ordercode
i.e. don't group in the order ID.
(I'm guessing that O20100812 was just an example and you actually want this for all order codes?)