Retrieve cost on certain date SQL - sql

I have the following tables:
Order (orderID, date, shipID)
Shipping (shipID, price)
PO (prodID, orderID, amount)
Price (prodID, fromDate, price)
I need to retrieve each order ID and the total price including the cost of the items in order + the cost of shipping purchased. The cost of the item has to be the cost of the item on the order date, not the most recent date. The Price table stores the different prices of a product starting at a particular date (fromDate attribute). Hence, the price of a product on day d is the price in the entry with the largest fromDate-value f such that f ≤ d. I understand I can use the command max(fromDate) to retrieve the latest price on an item, however, I cannot figure out how to get the price on a certain date. This is my code so far:
SELECT o.orderId, SUM(pr.price) + SUM(s.price) orderCost
FROM "Order" o
INNER JOIN Shipping s
ON o.shipId = s.shipId
INNER JOIN PO po
ON po.orderId = o.orderId
INNER JOIN Price pr
ON pr.prodId = po.prodId
GROUP BY o.orderId;

Try this
select o.orderId, SUM(pr.price) + SUM(s.price) orderCost
from [Order] o
INNER JOIN Shipping s ON o.shipId = s.shipId
inner join PO po on o.shipId = po.shipId
inner join (select top 1 price from Price pr where fromDate = (select max(fromDate)from Price pr where fromDate <= [date])) pr
on pr.prodID = po.prodID
GROUP BY o.orderId;

Related

SQL number of products bought by at least 5 unique customers

I have a database with following objects:
Price (prodID, from, price)
Product (prodID, name, quantity)
PO (prodID, orderID, amount)
Order (orderID, date, address, status, trackingNumber, custID, shipID)
Shipping (shipID, company, time, price)
Customer (custID, name)
Address (addrID, custID, address)
I am trying to return the names of products ordered by at least 5 different customers. My code is:
SELECT Product.name, COUNT(DISTINCT custId) as cust_count
FROM Product P
INNER JOIN PO
ON PO.prodId = P.prodId
INNER JOIN "Order" O
ON O.orderId = PO.orderId
INNER JOIN Customer C
ON C.custId = O.custId
HAVING COUNT(DISTINCT custId) > 4;
I am getting the following errors:
The multi-part identifier "Product.name" could not be bound" Ambiguous column name 'custID'
You need a GROUP BY -- and to use your table aliases:
SELECT p.name, COUNT(DISTINCT o.custId) as cust_count
FROM Product P INNER JOIN
PO
ON PO.prodId = P.prodId INNER JOIN
"Order" O
ON O.orderId = PO.orderId
GROUP BY p.name
HAVING COUNT(DISTINCT o.custId) > 4;
Note that the JOIN to Customer is not necessary because the id is in the Order table.
You also try this.I hope this will solve your problem
SELECT DISTINCT TOP (5) o.custId, p.name
FROM Order O INNER JOIN
PO
ON PO.orderID = O.orderID INNER JOIN
Product P
ON P.prodID = PO.prodID

Retrieving date an item was ordered on SQL

I have the following tables:
Order (orderID, date, shipID)
Shipping (shipID, price)
PO (prodID, orderID, amount)
Price (prodID, fromDate, price)
I need to retrieve each order ID and the total price including the cost of the items in order + the cost of shipping purchased. The cost of the item has to be the cost of the item on the order date, not the most recent date. The Price table stores the different prices of a product starting at a particular date (fromDate attribute). Hence, the price of a product on day d is the price in the entry with the largest fromDate-value f such that f ≤ d. I understand I can use the command max(fromDate) to retrieve the latest price on an item, however, I cannot figure out how to get the price on a certain date. This is my code so far:
SELECT o.orderId, SUM(pr.price) + SUM(s.price) orderCost
from "Order" o
INNER JOIN Shipping s ON o.shipId = s.shipId
INNER JOIN PO po ON o.orderId = po.orderId
INNER JOIN (SELECT TOP 1 price FROM Price pr WHERE
fromDate = (SELECT MAX(fromDate)FROM Price pr WHERE fromDate <= o."date")) pr
ON pr.prodID = po.prodID
GROUP BY o.orderId;
It gives the following error:
The multi-part identifier "o.date" could not be bound
I am not sure this would quite give me my desired result even if it ran though. Any ideas?
You can first filter the top price on or before your order date using a subquery before joining.
SELECT o.orderId, SUM(pr.price) + SUM(s.price) orderCost
from [Order] o
INNER JOIN Shipping s ON o.shipId = s.shipId
INNER JOIN PO po ON o.orderId = po.orderId
INNER JOIN
(SELECT TOP 1 price, prodID FROM Price pr WHERE
fromDate <= (select max([date]) from [Order])
order by fromDate desc) pr ON pr.prodID = po.prodID
GROUP BY o.orderId;
you rewrite your query like below
SELECT o.orderId, SUM(pr.price+s.price) orderCost
from "Order" o
INNER JOIN Shipping s ON o.shipId = s.shipId
INNER JOIN PO po ON o.orderId = po.orderId
INNER JOIN (SELECT max(fromDate) as fromDate, max(price) as price
,prodID FROM Price pr group by prodID
) pr
ON pr.prodID = po.prodID
where pr.fromDate <= o."date"
GROUP BY o.orderId;
You havn't selected "date" in the first statement that defines "o". Perhaps something like this would work?
with sales as
(
SELECT
o.orderId
, o.date
, SUM(pr.price) + SUM(s.price) orderCost
from "Order" o
INNER JOIN Shipping s ON o.shipId = s.shipId
INNER JOIN PO po ON o.orderId = po.orderId
INNER JOIN (SELECT TOP 1 price FROM Price pr WHERE
fromDate = (SELECT MAX(fromDate)FROM Price pr WHERE fromDate <= o.date)) pr ON pr.prodID = po.prodID
GROUP BY o.orderId, o.date
)
select
orderid
, orderCost
from sales

Joining 2 Many-To-Many Relationship Tables

Problem:
Find the net balance of the total order amount and total payments for each customer.
There are 4 tables involved: OrderDetails, Orders, Payments and Customer.
The total amount order = quantity order * price each [in OrderDetails]
The total payment = sum of different payments for the same order.
Customers are linked to Payments and Orders with CustomerNumber. Orders are linked to OrderDetails with OrderNumber.
I tried joining the 4 tables with the INNER JOIN function.
SELECT
c.customername,
SUM(od.quantityordered * od.priceeach) - SUM(p.amount) AS Net_Balance
FROM
(
(
orderdetails od
INNER JOIN orders o ON od.ordernumber = o.ordernumber
)
INNER JOIN customers c ON o.customernumber = c.customernumber
)
INNER JOIN payments p ON c.customernumber = p.customernumber
GROUP BY c.customername;
The expected results should be 0 for almost every customers.
However, what I have got is the total amount order and total payment are multiplied by some constants. Specifically, the total payment shown is multiplied by the number of payments for each order.
Anybody have any ideas to save my life?
This is a typical issue when dealing with N-M relationships. To solve it, one solution is to move the aggregation to subqueries:
SELECT c.customername, o.amt - p.amt AS Net_Balance
FROM customers c
INNER JOIN (
SELECT ord.customernumber, SUM(det.quantityordered * det.priceeach) as amt
FROM orders ord
INNER JOIN orderdetails det ON ord.ordernumber = det.ordernumber
GROUP BY ord.customernumber
) o ON o.customernumber = c.customernumber
INNER JOIN (
SELECT customernumber, SUM(amount) as amt
FROM payments
GROUP BY customernumber
) p ON p.customernumber = c.customernumber
SELECT c.customername, SUM(od.quantityordered*od.priceeach) as ordersum , SUM(p.amount) as paymentsum'
What's the result of the two columns ?
Is it what you want?

Joining issue with sql query

We are using shipworks application to manage our orders. With this, we have also developed a small tool which helps in generating different kind of reports based on shipworks data.
So, we are facing little problem with generating reports for sales by Customer. In this report, we are fetching following information:
1. Customer ID, BillFirstName, BillMiddleName, BillLastName, OrderTotal as total from Order table.
2. SalePrice from OrderItem table. Saleprice is the (quantity * unitprice). OrderItem table saves the products with quantity and unit price ordered in a particular order. We have relationship between Order and OrderItem table through OrderID.
3. Discount, Taxes and freight from OrderCharge table. Discount is the sum of all the amounts which have corresponding type column values (COUPON, PROMOTION DISCOUNT, REWARD, CREDIT, PROMOTION, FACEBOOK_FAN_REWARD, VOUCHER) and Taxes is the sum of amount which have corresponding type column values (TAX) and freight is sum of amount which have corresponding type column values (SHIPPING). We have relationship between OrderCharge and Order table through OrderID.
OverAll, we are fetching the above data against each customerID. We also pass some store condition and date condition to get data i.e order belongs to store as we passed and belongs to passed start and end date.
We have made the query for above as:
select derived.CustomerID, derived.BillFirstName, derived.BillMiddleName,
derived.BillLastName, SUM(oi.quantity*oi.UnitPrice) as saleprice, derived.freight,
derived.tax, sum(o.OrderTotal) as total, derived.discount
from (select o.CustomerID, o.BillFirstName, o.BillMiddleName, o.BillLastName
,SUM(oc.amount) as freight, SUM(oc2.amount) as tax, SUM(oc3.amount) as discount
from [Order] o
inner join OrderCharge oc on o.orderID = oc.orderID
and oc.[Type] = 'SHIPPING'
inner join OrderCharge oc2 on o.orderID = oc2.orderID
and oc2.Type = 'TAX'
inner join OrderCharge oc3 on o.orderID = oc3.orderID
and (oc3.Type = 'COUPON'
or oc3.Type = 'PROMOTION DISCOUNT'
or oc3.Type = 'REWARD'
or oc3.Type = 'CREDIT'
or oc3.Type = 'PROMOTION'
or oc3.Type = 'FACEBOOK_FAN_REWARD'
or oc3.Type = 'VOUCHER')
where o.StoreID IN(12005,17005,1005,20005,19005)
and (o.OrderDate between '2013-11-01 00:00:00' and '2013-12-27 23:59:00')
group by o.CustomerID, o.BillFirstName,
o.BillMiddleName, o.BillLastName) as derived
inner join [Order] o on o.CustomerID = derived.CustomerID
inner join orderItem oi on o.orderID = oi.orderID
group by derived.CustomerID, derived.BillFirstName, derived.BillMiddleName,
derived.BillLastName, derived.freight, derived.tax, derived.discount
The above query giving us right data but not summing the discount, freight and taxes. Can any one please suggest me other solution or tell me what is the wrong with the above query?
Waiting for reply
Try this:
SELECT o.CustomerID, o.BillFirstName, o.BillMiddleName, o.BillLastName,
SUM(B.saleprice) AS saleprice, SUM(A.freight) AS freight,
SUM(A.tax) AS tax, SUM(o.OrderTotal) AS total, SUM(A.discount) AS discount
FROM ORDER o
INNER JOIN (SELECT orderID,
SUM(CASE WHEN oc.TYPE = 'SHIPPING' THEN oc.amount ELSE 0 END) AS freight,
SUM(CASE WHEN oc.TYPE = 'TAX' THEN oc.amount ELSE 0 END) AS tax,
SUM(CASE WHEN oc.TYPE IN ('COUPON', 'PROMOTION DISCOUNT', 'REWARD', 'CREDIT', 'PROMOTION', 'FACEBOOK_FAN_REWARD', 'VOUCHER') THEN oc.amount ELSE 0 END) AS discount
FROM OrderCharge oc GROUP BY oc.orderID
) A ON o.orderID = A.orderID
INNER JOIN (SELECT orderID, SUM(oi.quantity * oi.UnitPrice) AS saleprice
FROM OrderItem oi GROUP BY oi.orderID
) B ON o.orderID = B.orderID
WHERE o.StoreID IN(12005,17005,1005,20005,19005) AND
o.OrderDate BETWEEN '2013-11-01 00:00:00' AND '2013-12-27 23:59:00'
GROUP BY o.CustomerID, o.BillFirstName, o.BillMiddleName, o.BillLastName

SQL selection criteria on grouped aggregate

I'm trying to find a simple MySQL statement for the following two problems:
I have 4 tables: Employees, Customers, Orders, Products (Each entry in Orders contains a date, a reference one product, a quantity and a reference to a customer, and a reference to an Employee).
Now I'm trying to get all customers where the volume of sale (quantity * product.price) is bigger in 1996 than in 1995.
And: I want to list all Employees whose volume of sale is below the average volume of sale.
Any help would really be appreciated. I've managed to get the information using a php script but I think this can be done with some clever SQL Statements.
Can anybody help me?
Employee Table: ID# Name
Products Table: ID# NAME# PRICE
Orders Table: ODERID# CUSTOMERID # DATE # EMPLOYEE# PRODUCTID# QUANTITY
For the first part (assuming quite a bit about the schema):
SELECT Customers.ID
FROM Customers
LEFT JOIN orders AS o1 ON o1.CustomerID=Customers.ID AND YEAR(o1.DATE) = 1995
LEFT JOIN products AS p1 ON p1.id = o1.productID
LEFT JOIN orders AS o2 ON o2.CustomerID=Customers.ID AND YEAR(o2.DATE) = 1996
LEFT JOIN products AS p2 ON p2.id = o2.productID
HAVING SUM(o1.quantity* p1.price) < SUM(o2.quantity*p2.price)
I don't know the database type you're using, so I'll use sqlserver. The 'Year' function is available on most databases, so you should be able to rewrite the query for your db in question.
I think this is the query which returns all customerid's + ordertotal for the customers which have a higher total in 1996 than in 1995, but I haven't tested it. Crucial is the HAVING clause, where you can specify a WHERE kind of clause based on the grouped result.
SELECT o.CustomerId, SUM(o.Quantity * p.Price) AS Total
FROM Orders o INNER JOIN Products p
ON o.ProductId = p.ProductId
WHERE YEAR(o.Date) == 1996
GROUP BY o.CustomerId
HAVING SUM(o.Quantity * p.Price) >
(
SELECT SUM(o.Quantity * p2.Price) AS Total
FROM Orders o2 INNER JOIN Products p2
ON o2.ProductId = p.ProductId
WHERE YEAR(o.Date) == 1995
AND o2.CustomerId = o.CustomerId
GROUP BY o.CustomerId
)
something like that:
select * from customers c
where (select sum (o.quantity * p.price) from orders o, product p where o.productID = p.productID and o.dateyear = 1996 and o.customerID = c.customerID) < (select sum (o.quantity * p.price) from orders o, product p where o.productID = p.productID and o.dateyear = 1995 and o.customerID = c.customerID)
select * from employees e where (select avg (o.quantity * p.price) from orders o, product p where o.productID = p.productID and o.empID = e.EmpID) < (select avg (o.quantity * p.price) from orders o, product p where o.productID = p.productID)