Finding Customers Last Price Paid - sql

I'm trying to find a way to get customers last price paid the code we have at the moment is:
SELECT Product.ProductCode,
COUNT(Product.ProductCode) AS [Qty Baught],
Product.Description,
Customer.CustomerCode,
Customer.Name,
MAX(OrderHeader.DateTimeCreated) AS [Date],
OrderLine.UnitSellPriceInCurrency AS Sell
FROM Customer
INNER JOIN OrderHeader ON Customer.CustomerID = OrderHeader.CustomerID
INNER JOIN OrderLine ON OrderHeader.OrderID = OrderLine.OrderID
INNER JOIN Product ON OrderLine.ProductID = Product.ProductID
GROUP BY Product.Description,
Product.ProductCode,
Customer.CustomerCode,
Customer.Name,
OrderLine.UnitSellPriceInCurrency
HAVING (Product.ProductCode = 'bcem002')
AND (Customer.CustomerCode = '1000')
ORDER BY MAX(OrderHeader.DateTimeCreated) DESC
This code shows every time the price changed but I only want to see the last price, But the DateCreated and the price paid (UnitSellPriceInCurrency) are on different tables.
Is there a way to Group (UnitSellPriceInCurrency) by (DateCreated) or an alternative way of doing it.
I'm fairly new at this so if there's an obvious way of doing this sorry.
Edit: What i'm getting at the moment with new code, Most of the prices i'm getting up are unrelated to the products
What I want is to get just the last price paid showing but in a way I can change the customer and the product that I'm searching for.

One option might be to use a sub-select utilizing TOP to specify that you only want to retrieve one record, and make sure that it is the "latest" by using the ORDER BY:
SELECT Product.ProductCode,
COUNT(Product.ProductCode) AS [Qty Baught],
Product.Description,
Customer.CustomerCode,
Customer.Name,
MAX(OrderHeader.DateTimeCreated) AS [Date],
(SELECT TOP 1 O.UnitSellPriceInCurrency
FROM OrderLine O
INNER JOIN OrderHeader OH ON O.OrderID = OH.OrderID
WHERE OH.CustomerID = Customer.CustomerID AND O.ProductID = Product.ProductID
ORDER BY OH.DateTimeCreated DESC) AS LatestPrice
FROM Customer
INNER JOIN OrderHeader ON Customer.CustomerID = OrderHeader.CustomerID
INNER JOIN OrderLine ON OrderHeader.OrderID = OrderLine.OrderID
INNER JOIN Product ON OrderLine.ProductID = Product.ProductID
WHERE (Customer.CustomerCode = '1000') AND (Product.ProductCode = 'bcem002')
GROUP BY Product.Description,
Product.ProductCode,
Product.ProductID,
Customer.CustomerCode,
Customer.Name,
Customer.CustomerID
ORDER BY [Date] DESC
In this example LatestPrice will contain the last inserted UnitSellPriceInCurrency for each Customer and product. I'm not sure if the query makes sense with your data (why get only the last price) but it's how I interpreted your request. The query will still return all OrderHeaders though.

Can you please check of this works alright. It would be better if you posted a snapshot of the current result and the expected result you need.
Select
*
FROM
(
SELECT Product.ProductCode,
COUNT(Product.ProductCode) AS [Qty Baught],
Product.Description,
Customer.CustomerCode,
Customer.Name,
OrderHeader.DateTimeCreated AS [Date],
OrderLine.UnitSellPriceInCurrency AS Sell
RANK() OVER (PARTITION BY Customer.CustomerCode,Customer.Name, OrderLine.UnitSellPriceInCurrency ORDER BY OrderHeader.DateTimeCreated) rnk
FROM Customer
INNER JOIN OrderHeader ON Customer.CustomerID = OrderHeader.CustomerID
INNER JOIN OrderLine ON OrderHeader.OrderID = OrderLine.OrderID
INNER JOIN Product ON OrderLine.ProductID = Product.ProductID
WHERE Product.ProductCode = 'bcem002'
AND Customer.CustomerCode = '1000'
GROUP BY Product.Description,
Product.ProductCode,
Customer.CustomerCode,
Customer.Name,
OrderLine.UnitSellPriceInCurrency
) tbl1
WHERE tbl1.rnk =1
;

Related

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

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);

How to multiply 2 columns and then SUM the results?

I'm learning SQL and I couldn't find the solution to my problem anywhere on he forums. Anyway, I'm using a www.dofactory.com SQL Sandbox and I've made a query:
select customer.LastName, Product.ProductName, OrderItem.Quantity, Product.UnitPrice, OrderItem.Quantity*Product.UnitPrice AS "Quantity x UnitPrice"
FROM Customer
JOIN [Order] ON [Order].CustomerID = Customer.ID
JOIN OrderItem ON OrderItem.OrderId = [Order].ID
JOIN Product ON Product.Id = OrderItem.ProductId
where
[Order].TotalAmount = (select max([Order].TotalAmount) FROM [Order])
And result:
LastNam ProductName Quantity UnitPrice Quantity x UnitPrice
Kloss Côte de Blaye 60 263.50 15810.00
Kloss Chartreuse verte 80 18.00 1440.00
Now I want to SUM the whole Column "Quantity x UnitPrice". What should I do?
You use SUM(). Something like this:
SELECT SUM(oi.Quantity * oi.UnitPrice) AS Summary
FROM Customer c JOIN
[Order] o
ON o.CustomerID = c.ID JOIN
OrderItem oi
ON oi.OrderId = o.ID JOIN
Product p
ON p.Id = oi.ProductId
WHERE o.TotalAmount = (select max(o2.TotalAmount) FROM [Order] o2);
Note the use of table aliases. They make the query easier to write and to read.
This is SQL Server (T-SQL). You can use SUM and GROUP BY like so. I've done it in a subquery, which is how I'd approach this sort of thing.
select LastName, ProductName, Quantity, UnitPrice, SUM(Summary)
from (
select customer.LastName, Product.ProductName, OrderItem.Quantity, Product.UnitPrice, OrderItem.Quantity*OrderItem.UnitPrice AS Summary, [Order].TotalAmount
FROM Customer
JOIN [Order] ON [Order].CustomerID = Customer.ID
JOIN OrderItem ON OrderItem.OrderId = [Order].ID
JOIN Product ON Product.Id = OrderItem.ProductId
where
[Order].TotalAmount = (select max([Order].TotalAmount) FROM [Order])) x
group by LastName, ProductName, Quantity, UnitPrice

SQL query with w3schools db

I should have asked multiple questions in my other post. Thanks to all who have helped, I am now stuck on another one..
Using the w3schools db, List SupplierID, SupplierName and ItemSupplied (count of number of items supplied by a supplier), sort the list first by number of items supplied (descending) and then by supplier name (ascending)
SELECT supplierid,
suppliername,
p.productname,
Count(s.supplierid) AS itemssupplied
FROM [Suppliers] AS s
INNER JOIN [Products] AS p
ON p.supplierid = s.supplierid
GROUP BY p.productid,
p.productname
ORDER BY Count (p.productid, p.productname) DESC
order BY s.suppliername
It's giving me an error, then again I am ordering by multiple ones. I think there's something I am not quite understanding here.
My other question is
List customers for each category and the total of order placed by that customer in a given category. In the query show three columnm: CategoryName, CustomerName, and TotalOrders (which is price * quantity for orders for a given customer in a given category). Sort this data in descending order by TotalOrders.
SELECT cg.CategoryName,
c.CustomerName,
Sum(p.Price * od.Quantity) AS TotalOrders
FROM [products] AS p
INNER JOIN [orderdetails] AS od
ON od.ProductID = p.ProductID
INNER JOIN [orders] AS o
ON o.OrderID = od.OrderID
INNER JOIN [customers] AS c
ON c.customerID = o.CustomerID
INNER JOIN [categories] AS cg
ON cg.CategoryID = p.CategoryID
GROUP BY c.CustomerName
ORDER BY TotalOrders DESC
Can someone please check if my query is correct? Thank you once again!
Question 1
You are really close but you only need to state ORDER BY once (also make sure to include all shown fields in your GROUP BY unless you are aggregating them):
SELECT SupplierID, SupplierName, p.ProductName, count(s.SupplierID) AS ItemsSupplied
FROM [Suppliers] AS s
INNER JOIN [Products] AS p ON p.SupplierID = s.SupplierID
GROUP BY p.ProductID, p.ProductName, SupplierID, SupplierName -- Added SupplierID, SupplierName
ORDER BY COUNT (p.productID, p.ProductName) DESC, s.SupplierName
Notice that you just place multiple sorts on the same line with a comma separating them.
Question 2
You're almost there but you need to group by any field that is not being aggregated. So in order not to get a parsing error, I added the cg.CategoryName to the GROUP BY line.
SELECT cg.CategoryName, c.CustomerName, Sum(p.Price*od.Quantity) AS TotalOrders
FROM [Products] AS p
INNER JOIN [OrderDetails] AS od ON od.ProductID = p.ProductID
INNER JOIN [Orders] AS o ON o.OrderID = od.OrderID
INNER JOIN [Customers] AS c ON c.customerID = o.CustomerID
INNER JOIN [Categories] AS cg ON cg.CategoryID = p.CategoryID
GROUP BY c.CustomerName, cg.CategoryName --Added CategoryName
ORDER BY TotalOrders DESC
You have several problems with the first query:
You're grouping by ProductID and ProductName even though you want the number of items supplied by a supplier, which means that you want to group by SupplierID and SupplierName.
You're supplying too many arguments to the COUNT function, which takes a single column name or *.
You've included a ProductName column in your results, which is not called for.
You need to ORDER BY both the number of products supplied and the SupplierName.
With those points in mind:
SELECT
s.SupplierID,
s.SupplierName,
COUNT(p.ProductID) AS ItemsSupplied
FROM
[Suppliers] AS s
INNER JOIN [Products] AS p ON p.SupplierID = s.SupplierID
GROUP BY
s.SupplierID, s.SupplierName
ORDER BY
ItemsSupplied DESC,
s.SupplierName ASC
Your second query is quite close, you're just missing one point, which is that you're looking for total of order placed by that customer in a given category. This means that in addition to grouping by c.CustomerName, you need to group by cg.CategoryID:
SELECT
cg.CategoryName,
c.CustomerName,
SUM(p.Price*od.Quantity) AS TotalOrders
FROM
[Products] AS p
INNER JOIN [OrderDetails] AS od ON od.ProductID = p.ProductID
INNER JOIN [Orders] AS o ON o.OrderID = od.OrderID
INNER JOIN [Customers] AS c ON c.customerID = o.CustomerID
INNER JOIN [Categories] AS cg ON cg.CategoryID = p.CategoryID
GROUP BY
c.CustomerName, cg.CategoryID
ORDER BY
TotalOrders DESC
The first one has two order by clauses
ORDER BY COUNT (p.productID, p.ProductName) DESC
and
ORDER BY s.SupplierName
also some databases will complain when order by columns for queries using group by are not included in the selected columns

SQL Server Aggregation using Max() and obtaining details from max() line.

I just took a final exam and one of the questions asked me to double join three tables, and report the max sale payout for each salesperson.
The tables have the following variables:
Salesperson(id, name)
Order(orderid, order_date, Cust_id, Saleperson_id, amount)
Customer(id, name)
After joining:
select salesperson.Name, Orders.Number, customer.Name, Orders.Amount
from Orders
join salesperson
on orders.Salesperson_id = salesperson.ID
join Customer
on customer.ID = orders.cust_id
What the instructed wanted was for me to find each salesperson's maximum sell (as found by order.amount). He also wanted the salesperson (salesperson.name), the order number of the max sale (orders.number), the customer the sale was with (customer.name), and the max sale amount. What is the most efficient way to do this problem? I have tried to use "group by salesperson.name", but I cannot because the orders.number and customer.name are never held in the aggregation.
I finished the problem this way
select
salesperson.name as Sales_Person,
orders.number as Order_Number,
customer.Name as Customer_Name,
orders.Amount as Sale_Amount
from salesperson
left join Orders
on salesperson.ID = orders.Salesperson_id
left join Customer
on orders.cust_id = customer.ID
where orders.Amount in (select max(orders.Amount)
from salesperson
join Orders
on salesperson.ID = orders.Salesperson_id
join Customer
on orders.cust_id = customer.ID
group by salesperson.name)
I know this is a bad way to do it. For instance, what if two different salesperson's max sale was equivalent? Max and min are not like count and sum because it is picking out one line from a aggregation, but the rules still apply. Also, you might notices that there is no real unique identifier in the joined table other than order.number which is not useful. Therefore, I would have to use some composite of salesperson.name and order.number.
Also, what do I do if I have to pick the top three sales for each salesperson? Should such an output be totally different code-wise than what would be required from just the first sale?
I keep bumping me head against this problem, and I would love to have a more professional approach to this problem.
SELECT
M.max_amount,
S.Name,
O.Number,
C.Name
FROM orders O
JOIN salesperson S
ON S.Salesperson_id = O.Salesperson_id
JOIN customer C
ON C.Customer_id = O.Customer_id
JOIN (
SELECT Salesperson_id, MAX(amount) max_amount
FROM Order
GROUP BY Salesperson_id
) M
ON M.Salesperson_id = O.Salesperson_id AND M.max_amount = O.amount
For the top 3:
SELECT
M.Amount,
S.Name,
O.Number,
C.Name
FROM orders O
JOIN salesperson S
ON S.Salesperson_id = O.Salesperson_id
JOIN customer C
ON C.Customer_id = O.Customer_id
CROSS APPLY (
SELECT TOP 3 Amount
FROM Order
WHERE Salesperson_id = O.Salesperson_id
ORDER BY Amount DESC
) M