SQL sum from single table with join - sql

I have two table orders and orderitems.
order table has id,order_total,recieved_amount
orderitems table has id,order_id,name,total_item
I want the sum of recieved_amount, order_total from the order table and sum of total_item from orderitems. so I used
SELECT SUM(`received_amount`) as totalRecieved,
SUM(`order_total`) as orderTotal
FROM `orders` AS `Order`
LEFT JOIN `order_items` AS `OrderItems`
ON (`OrderItems`.`order_id`=`Order`.`id`)
and
SELECT SUM(`received_amount`) as totalRecieved,
SUM(`order_total`) as orderTotal
FROM `orders` AS `Order`
LEFT JOIN `order_items` AS `OrderItems`
ON (`OrderItems`.`order_id`=`Order`.`id`)
group by order.id
but none of them is giving me the correct result.

You are aggregating at two levels of your data hierarchy. This causes a problem with Cartesian products, for each order.
The solution is to aggregate along order_items before doing the join:
SELECT SUM(received_amount) as totalRecieved,
SUM(order_total) as orderTotal
FROM orders o LEFT JOIN
(SELECT oi.order_id, SUM(total_items) as total_items
FROM order_items oi
GROUP BY oi.order_id
) oi
ON oi.order_id = o.id;

As an alternative, you can benefit from cte structure or a temp table like below:
;with cte (order_id, SumTotalItems) as (
SELECT oi.order_id, SUM(total_items) as SumTotalItems
FROM order_items oi
GROUP BY oi.order_id
)
select sum(o.receivedamount) as SumReceivedAmount
, sum(o.order_total) as SumOrderTotal
, cte.SumTotalItems
from orders o
left outer join cte on o.id = cte.order_id

Related

SQL order minimum Query

I'm trying to query the products not ordered since 01/01/2017 in SSMS.
So far I've come up with a couple of select count queries but have come up empty trying to figure this out. This has 3 tables attached to the query and I need the product names and IDs attached to the query result.
products table columns:
[product_id], [product_name], [brand_id], [category_id], [model_year], [list_price]
orders table columns:
[order_id], [item_id], [product_id], [quantity], [list_price], [discount]
order_items table columns:
[order_id], [customer_id], [order_status], [order_date], [required_date], [shipped_date],[store_id], [staff_id]
SELECT COUNT (*)
FROM production.products
WHERE NOT EXISTS (SELECT 1
FROM sales.orders
JOIN sales.order_items oi ON orders.order_id = oi.order_id
WHERE orders.order_id = oi.order_id
AND orders.order_date > '2017-01-01');
Break it down into three parts
Order items and orders joined in the date range
Products not in #1
WITH prodcuts_in_date_range as
(
SELECT DISTINCT oi.Product_id
FROM Order_items oi INNER JOIN Orders o on o.Order_id = oi.Order_id
WHERE oi.Order_date > '2017-01-01')
)
SELECT * FROM Products p where p.Product_Id not in (SELECT Product_id from
products_in_date_range)

How to create a function that totals an order with several items?

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;

sql get newest date and price of all inventory_items

I have this sql tables, and i need to get from all inventory items the newest date from table: orders with the price paid on this date
table:orders
id
date
table:order_items
order_id
inventory_id
price
table:inventory
item_number
if i do something like that:
SELECT inventory.item_number, orders.date, order_items.price
FROM inventory
INNER JOIN order_items ON inventory.id = order_items.inventory_id
INNER JOIN orders ON order_items.order_id = orders.id
WHERE max(orders.date)
it's not working, and i get an error.
What is the correct way to do that
You need a where clause, but the MAX() cannot go there directly. Try a subquery:
SELECT i.item_number, o.date, orders.price
FROM inventory i INNER JOIN
order_items oi
ON i.id = oi.inventory_id INNER JOIN
orders o
ON oi.order_id = o.id
WHERE o.date = (SELECt max(o2.date) FROM orders o2);

Need multiple rows with same value IN OPERATOR

Suppose, order_id 4646, 4647 and 4648 are from same customer.
SELECT customer_id FROM orders WHERE order_id IN (4646, 4647, 4648)
Result:
customer_id
2589
2589
2589
Every customer has a gcm_registration_token.
SELECT gcm_registration_token FROM customer_details WHERE customer_id IN (2589, 2589, 2589)
Result:
gcm_registration_token
dyB_PhRHddU:APA91bGAbuxAIlHUmH2XYK0pWM3ON37O_mTF7g...
I want the second query to return 3 rows with same gcm_registration_token.
Expected result:
gcm_registration_token
dyB_PhRHddU:APA91bGAbuxAIlHUmH2XYK0pWM3ON37O_mTF7g...
dyB_PhRHddU:APA91bGAbuxAIlHUmH2XYK0pWM3ON37O_mTF7g...
dyB_PhRHddU:APA91bGAbuxAIlHUmH2XYK0pWM3ON37O_mTF7g...
A way around would be to fire query for each value. But, is it possible with single query.
Use JOIN like this:
SELECT c.gcm_registration_token
FROM orders o
JOIN customer_details c ON c.customer_id = o.customer_id
WHERE o.order_id IN (4646, 4647, 4648)
You can use INNER JOIN in following:
SELECT gcm_registration_token
FROM orders o
INNER JOIN customer_details d ON o.customer_id = d.customer_id
WHERE order_id IN (4646, 4647, 4648)
use INNER JOIN
SELECT `gcm_registration_token`
FROM `orders` o
INNER JOIN `customer_details` c ON `o`.`customer_id` = `c`.`customer_id`
WHERE `o`.`order_id` IN (4646, 4647, 4648)
select ord.customer_id as customerid , cd.gcm_registration_token from orders as ord
left join customer_details as cd on cd.customer_id = ord.customer_id
WHERE ord.order_id IN (4646, 4647, 4648);
This query would mix customer detail table and order table and return all values that matches the where clause on the left table

SQL Query for counting number of orders per customer and Total Dollar amount

I have two tables
Order with columns:
OrderID,OrderDate,CID,EmployeeID
And OrderItem with columns:
OrderID,ItemID,Quantity,SalePrice
I need to return the CustomerID(CID), number of orders per customer, and each customers total amount for all orders.
So far I have two separate queries. One gives me the count of customer orders....
SELECT CID, Count(Order.OrderID) AS TotalOrders
FROM [Order]
Where CID = CID
GROUP BY CID
Order BY Count(Order.OrderID) DESC;
And the other gives me the total sales. I'm having trouble combining them...
SELECT CID, Sum(OrderItem.Quantity*OrderItem.SalePrice) AS TotalDollarAmount
FROM OrderItem, [Order]
WHERE OrderItem.OrderID = [Order].OrderID
GROUP BY CID
I'm doing this in Access 2010.
You would use COUNT(DISTINCT ...) in other SQL engines:
SELECT CID,
Count(DISTINCT O.OrderID) AS TotalOrders,
Sum(OI.Quantity*OI.SalePrice) AS TotalDollarAmount
FROM [Order] O
INNER JOIN [OrderItem] OI
ON O.OrderID = OI.OrderID
GROUP BY CID
Order BY Count(DISTINCT O.OrderID) DESC
Which Access unfortunately does not support. Instead you can first get the Order dollar amounts and then join them before figuring the order counts:
SELECT CID,
COUNT(Orders.OrderID) AS TotalOrders,
SUM(OrderAmounts.DollarAmount) AS TotalDollarAmount
FROM [Orders]
INNER JOIN (SELECT OrderID, Sum(Quantity*SalePrice) AS DollarAmount
FROM OrderItems GROUP BY OrderID) AS OrderAmounts
ON Orders.OrderID = OrderAmounts.OrderID
GROUP BY CID
ORDER BY Count(Orders.OrderID) DESC
If you need to include Customers that have orders with no items (unusual but possible), change INNER JOIN to LEFT OUTER JOIN.
Create a query which uses your 2 existing queries as subqueriers, and join the 2 subqueries on CID. Define your ORDER BY in the parent query instead of in a subquery.
SELECT
sub1.CID,
sub1.TotalOrders,
sub2.TotalDollarAmount
FROM
(
SELECT
CID,
Count(Order.OrderID) AS TotalOrders
FROM [Order]
GROUP BY CID
) AS sub1
INNER JOIN
(
SELECT
CID,
Sum(OrderItem.Quantity*OrderItem.SalePrice)
AS TotalDollarAmount
FROM OrderItem INNER JOIN [Order]
ON OrderItem.OrderID = [Order].OrderID
GROUP BY CID
) AS sub2
ON sub1.CID = sub2.CID
ORDER BY sub1.TotalOrders DESC;