Getting data from a JOIN in SQL - sql

Sorry for the messy name of the question, this is my first SQL one.
Does anyone know how to get the OrderID of an Order where the max quantity of a product was sold?
This is my code by far:
SELECT Products.ProductName, MAX([Order Details].Quantity), MAX(OrderID)
FROM Products
INNER JOIN [Order Details] ON Products.ProductID = [Order Details].ProductID
GROUP BY Products.ProductName
When I say MAX(OrderID) I get the Highest ID where the product was sold, not the actual ID where the Highest quantity of the product was sold.
This is my first question about SQL, Sorry for any lack of information, just tell me what is needed and I'll add it. Thanks in advance!
EDIT: I'm using SQL Server 2008

You can use analytical functions for this:
UPDATED
SELECT ProductName, Quantity, OrderID
FROM ( SELECT Products.ProductName, [Order Details].Quantity, OrderID,
ROW_NUMBER() OVER(PARTITION BY Products.ProductName ORDER BY [Order Details].Quantity DESC) Corr
FROM Products
INNER JOIN [Order Details] ON Products.ProductID = [Order Details].ProductID) A
WHERE Corr = 1
This way you will get only one record per Product, that means that if you have more than one Order with the same max quantity, you are only getting one as result. You can add more columns (order date for example) on the ORDER BY to choose the newest or oldest of those. If you want to get all the records that are tied on the quantity, then you can use RANK instead of ROW_NUMBER.
SELECT ProductName, Quantity, OrderID
FROM ( SELECT Products.ProductName, [Order Details].Quantity, OrderID,
RANK() OVER(PARTITION BY Products.ProductName ORDER BY [Order Details].Quantity DESC) Corr
FROM Products
INNER JOIN [Order Details] ON Products.ProductID = [Order Details].ProductID) A
WHERE Corr = 1

SELECT Products.ProductName, [Order Details].OrderID, [Order Details].Qty
FROM Products
INNER JOIN [Order Details] ON Products.ProductID = [Order Details].ProductID
WHERE [Order Details].Quantity = (SELECT MAX(p.Quantity) FROM [Order Details] p WHERE p.ProductID = Products.ProductID)
Note: this will give you multiple results for a single product, if you have multiple orders with max quantity ordered.

Related

Select aggregate from multiple tables

I have 2 tables which are:
and
I want to select Total Item Line Amount in each Order which is calculated by UnitPrice*Quantity, Total Discount = sum(((Quantity * UnitPrice)/100) * Discount*100) and AverageFreight = (Freight/Total Item In Order) * Total Line Item In Order
I write select statement like this:
select Orders.OrderID,CustomerID, EmployeeID, ProductID,ShippedDate, RequiredDate, ShipVia,(Freight/sum(Quantity))*Quantity 'TotalFreight',
Quantity * UnitPrice 'LineItemTotal',sum(Quantity) 'Line Item Quantity',sum(((Quantity * UnitPrice)/100) * Discount*100) 'Total Line Discount',Discount from Orders
inner join [Order Details] on Orders.OrderID = [Order Details].OrderID
group by Orders.OrderID,Orders.CustomerID, Orders.EmployeeID, [Order Details].ProductID, Orders.RequiredDate, Orders.ShipVia, Orders.Freight, [Order Details].Quantity,[Order Details].UnitPrice, [Order Details].Discount, Orders.ShippedDate
However, it does not calculate the AverageFreight right. What am I doing wrong?
You don't need aggregation for this. A window function should suffice:
select o.*, od.*,
(Freight / order_quantity)*Quantity as AllocatedFreight,
Quantity * UnitPrice as LineItemTotal,
Quantity as [Line Item Quantity],
(((Quantity * UnitPrice)/100) * Discount*100) as [Total Line Discount,
Discount
from Orders o inner join
(select od.*, sum(quantity) over (partition by od.orderId) as order_quantity
from [Order Details] od
) od
on o.OrderID = od.OrderID;

Trying to sum part of the rows

So I have three tables
Orders:
CustomerID,OrderID
Order Details;
OrderID,ProductId,UnitPrice,Quantity,Discount
And Products:
ProductID,ProductName
And I need to combine these 2 tables and create this one:
[Orderd Details].CustomersID,Products.ProductName,FORMULA
Formula is how much money people spent money on this product. So I think I have to sum UnitPrice* Quantity*(1-Discount) from every order for this product.
Sadly I have no idea how should I do it. The best I did is:
SELECT o.CustomerID,p.ProductName,SUM(od.Quantity*od.UnitPrice*(1-od.Discount)) as 'SKZ'
FROM Customers as c, Orders as o,[Order Details] as od,Products as p
WHERE (o.OrderID=od.OrderID AND p.ProductID=od.ProductID)
GROUP BY od.ProductID ORDER BY o.CustomerID;
But it doesn't work.
First, learn explicit JOIN syntax. Simple rule: Never use commas in the FROM clause.
Second, you should include all non-aggregated columns in the GROUP BY:
SELECT o.CustomerID, p.ProductName,
SUM(od.Quantity * od.UnitPrice * (1 - od.Discount)) as SKZ
FROM Orders as o JOIN
[Order Details] od
ON o.OrderID = od.OrderID JOIN
Products p
ON p.ProductID = od.ProductID
GROUP BY o.CustomerID, p.ProductName
ORDER BY o.CustomerID;

Subquery between three tables using Northwind database with SQL Server

Table [Orders] : OrderID(Primary Key), CustomerID
Table [Order Details] : OrderID(Primary Key), ProductID(Primary Key), Discount
Table [Customers] : CustomerID[Primary Key]
With these three tables, I want to query productID with highest discount for each CustomerID. I need column for ProductID, CustomerID and Discount. How can I solve this problem? All kinds of helps are really appreciated.
Following script I have tried :
select ProductID, a.customerID,
(select MAX(discount)
from [Order Details]
where a.CustomerID=c.customerID
)
from Orders a
join [Order Details]
on a.OrderID=[Order Details].OrderID
join Customers c
on a.CustomerID=c.CustomerID
order by customerID
The following query will return to you the productid with maximum discount for each customer. Please note that if for specific customer, you have more than one product that might have the max discount, I you want to return them, then you need to replace ROW_NUMBER() with DENSE_RANK()
WITH CTE AS
(SELECT ProductID,
o.CustomerID,
Discount,
ROW_NUMBER() OVER(PARTITION BY o.CustomerID ORDER BY Discount DESC) Row_num
FROM [Order Details] od INNER JOIN Orders o
ON od.OrderID= o.OrderID
)
SELECT ProductID,
CustomerID,
Discount
FROM CTE
WHERE Row_num = 1

Does this SQL statement require a nested SELECT query?

Here is what I have so far but the results are wrong.
SELECT c.CompanyName,
COUNT(o.OrderID) AS [Total Orders],
SUM(
(od.UnitPrice -
(od.UnitPrice * od.Discount))* Quantity) AS [Purchase Total]
FROM Customers AS c,
Orders AS o,
[Order Details] AS od
WHERE c.CustomerID = o.CustomerID
AND o.OrderID = od.OrderID
GROUP BY c.CompanyName
ORDER BY c.CompanyName;
The issue I am having is with the count, it is off by double or more. I believe that this is because the OrderID appears multiple times in the Order Details table. I think I need a nested SELECT statement but I am unsure how to do that.
Would I be removing the SUM() expression, Order Details, and the AND clause from the first query? Or am I way off?
With help I have gotten the COUNT field to work but now my SUM field is wrong. This is my most recent attempt and it produces the same value for every customer.
SELECT c.CompanyName,
COUNT(o.OrderID) AS [Total Orders],
(SELECT SUM(
(odIN.UnitPrice -
(odIN.UnitPrice * odIN.Discount)) * odIN.Quantity) AS [OrderTotal]
FROM [Order Details] AS odIN, Orders As oIN
WHERE odIN.OrderID = oIN.OrderID) AS [Purchase Total]
FROM
Customers AS c, Orders AS o
WHERE c.CustomerID = o.CustomerID
GROUP BY c.CompanyName
ORDER BY c.CompanyName;
I was unsuccessful at getting the query to fully work the way I wanted it to. Then I realized that maybe maybe I was looking for the wrong data. So I switched the name for the COUNT field to Num Products Purchased.
I would still like to get the other way working, but I think that will require creating a temporary table or view that could be used to do one of the calculations and then call it from the query. That is something I'll have to figure out.
Thank you for the attempts to help.
Because Access doesn't have COUNT(DISTINCT) then you need to create an inner query.
What this does is compute the sum of each item in an order in the inner query, and then sums up all the order totals for the customer as the purchase total. An individual OrderID will not be counted twice, as o and od now have a one to one relationship.
There might be a syntax error in there somewhere, but the idea should work.
SELECT c.CompanyName,
COUNT(o.OrderID) AS [Total Orders],
SUM(od.OrderTotal) AS [Purchase Total]
FROM
Customers AS c,
Orders AS o,
(SELECT odIn.OrderID,
SUM(
(odIn.UnitPrice -
(odIn.UnitPrice * odIn.Discount)) * odIn.Quantity) AS [OrderTotal]
FROM [Order Details] AS odIn
GROUP BY odIn.OrderID) AS od
WHERE c.CustomerID = o.CustomerID
AND o.OrderID = od.OrderID
GROUP BY c.CompanyName
ORDER BY c.CompanyName;
if the problem is because OrderID appears multiple times, try:
SELECT c.CompanyName, COUNT(DISTINCT o.OrderID) AS [Total Orders], SUM((od.UnitPrice - (od.UnitPrice * od.Discount)) * Quantity) AS [Purchase Total]
FROM Customers AS c, Orders AS o, [Order Details] AS od
WHERE c.CustomerID = o.CustomerID AND o.OrderID = od.OrderID
GROUP BY c.CompanyName
ORDER BY c.CompanyName;
The distinct clause lets you count only each appearance.
First I would like to thank Daniel for his help. I did finally get the query to work with help from another source. Daniel's solution is better as it requires less code and even formats the sum in currency.
Here is the one I got to work:
SELECT vtOrdCnt.*, ROUND(vtTotCost.PurchaseTotal, 2) AS [Purchase Total]
FROM
(
SELECT CustomerID, COUNT(OrderID) AS TotalOrders
FROM orders
GROUP BY CustomerID
) AS vtOrdCnt,
(
SELECT CustomerID, SUM(UnitPrice * (1-Discount)*Quantity) AS PurchaseTotal
FROM Orders AS o, [Order Details] AS od
WHERE o.orderID = od.orderID
GROUP BY CustomerID
) AS vtTotCost
WHERE vtOrdCnt.CustomerID = vtTotCost.CustomerID
ORDER BY vtOrdCnt.CustomerId
By using Aliases and two select statements in the FROM clause it allowed the query to function the way I wanted it to.

How to use Max function on another column from a select

There is query which is asking for favourite products which is bought by each coustomer. i have to select and in the first select i have selected the count of products that each customer bought. in the other select i want to select the maximum of that boughts for each customer.but when i want to select max(previous select column) it gets and error and says it is not defined can any one helps me how to fix this problem. i am very motivated to solve the problem from this way, and i am not willing to use other methods like creating view or something like that. can any one help me on this:
SELECT INN.Maximum,INN.Name, customer.ProductName from
(SELECT ContactName, ProductName, COUNT([Order Details].Quantity) AS NumOftimeCustomer
FROM Orders, [Order Details], Products, Customers
WHERE [Order Details].OrderID = Orders.OrderID
AND [Order Details].ProductID = Products.ProductID
AND Orders.CustomerID = Customers.CustomerID
GROUP BY ContactName, ProductName)customer
INNER JOIN
(SELECT Customers.ContactName AS Name, **MAX(customer.numOftimecustomer)** AS Maximum
from Customers, customer
GROUP BY Customers.ContactName) INN
ON INN.Name = customer.ContactName AND INN.Maximum = customer.NumOftimeCustomer
that part which is mentioned with MAX(customer.numOftimecustomer) ** is the part which gives error and it says the object customer is not defined. is there a way to solve it without view? why is it in this way? since the customer that i defined is not a table?
here is what you want:
select
*
from (SELECT ContactName, ProductName, COUNT([Order Details].Quantity) AS NumOftimeCustomer
FROM Orders, [Order Details], Products, Customers
WHERE [Order Details].OrderID = Orders.OrderID
AND [Order Details].ProductID = Products.ProductID
AND Orders.CustomerID = Customers.CustomerID
GROUP BY ContactName, ProductName)customer
where customer.num = (select max(num) from
(SELECT ContactName, ProductName, COUNT([Order Details].Quantity) AS NumOftimeCustomer
FROM Orders, [Order Details], Products, Customers
WHERE [Order Details].OrderID = Orders.OrderID
AND [Order Details].ProductID = Products.ProductID
AND Orders.CustomerID = Customers.CustomerID
GROUP BY ContactName, ProductName)customer2
where customer2.name = customer.name)