Subquery between three tables using Northwind database with SQL Server - sql

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

Related

How do you add OrderID to this? I cant get it to display without getting a error on all OrderID sections

I cant get it to display without getting an error on all OrderID sections. I tried adding it to the top and then the subquery and it errors saying ambouious column. How would be the correct way to do this?
TABLE SETUP:
Customers Table:
CustomerID, EmailAddress, Password, FirstName, LastName, ShippingAddressID, BillingAddressID
OrderItems Table:
ItemID, OrderID, ProductID, ItemPrice, DiscountAmount, DiscountTotal, PriceTotal, ItemTotal, Quantity
Order Table:
OrderID, CustomerID, OrderDate, ShipAmount, TaxAmount, ShipDate, ShipAddressID, CardType, CardNumber,CardExpires, BillingAddressID
CODE:
SELECT c.EmailAddress, MAX(OrderCost) AS
LargestOrder
FROM Customers c
JOIN ORDERS o ON c.CustomerID = o.CustomerID
JOIN (Select Orders.OrderID, ItemPrice * Quanity AS OrderCost FROM Orders, OrderItems
WHERE OrderItems.OrderID = Orders.OrderID)Largest
ON Largest.OrderID = o.OrderID
GROUP BY c.EmailAddresses
It really helps for you to put some effort into a script that demonstrates your problem. That way no one needs to guess about how you defined things and the actual values you use.
Here is one approach based on my guess. Note "one" - there are techniques to achieve the same result. The cte calculates the total cost for each order just like your code attempted. Since you suggested top, I used that as well to demonstrate its usage. Grabbing the top first row based on descending OrderCost will get you the order with the highest total cost. Just join the cte to Orders and Customers to include the columns you desire.
with cte as (select OrderID, sum(ItemPrice * Quantity) as OrderCost
from #OrderItems
group by OrderID)
select top 1 Ord.OrderID, Ord.OrderDate, cust.EmailAddress, cte.OrderCost
from cte inner join #Orders as Ord
on cte.OrderID = Ord.OrderID
inner join #Customers as Cust
on Ord.CustomerID = Cust.CustomerID
order by cte.OrderCost desc;
rextester here
And everyone hopes that you are not actually saving credit card information - because that would be bad in many ways.

Query to pull second order date for a customer(SQL 2014)

I have a schema with customers, orders and order dates.
A customer can have orders in multiple dates. I need a calculated member to bring the first order date and the second order date with other associated metrics.
I was able to get the first order date and associated data using min(order date) as a first order but having issues querying for the second order date. Any suggestion would help! Thanks
my query
---I have all the information in one table so my query looks like
Select customerid, order id, min(orderdate) as firstorderdate,...
From customer Where first ordedate between 01/01/2015’ and GETDATE()
(since I only want those customers who made their first purchase this year)
Query their second purchase
Select customerid, orderid, orderdate from ( select customerid,
orderid, orderdate, rwo_number() over (partition by customerid,
orderid order by orderdate) rn from customer
Where rn<=2
Without seeing your current query, it's difficult to understand. I assume your current query is like this:
select c.customerid, o.orderid, min(od.orderdate)
from customers c
join orders o on c.customerid = o.customerid
join orderdates od on o.orderid = od.orderid
group by c.customerid, o.orderid
Another way of doing the same query is to use row_number. Doing it this way, you're not restricted to just the first in the group:
select customerid, orderid, orderdate
from (
select c.customerid, o.orderid, od.orderdate,
row_number() over (partition by c.customerid, o.orderid
order by od.orderdate) rn
from customers c
join orders o on c.customerid = o.customerid
join orderdates od on o.orderid = od.orderid
) t
where rn <= 2

SQL Server 2012 Query Confusion

I am a beginner with SQL and I cannot seem to come up with a correct query for this question:
Use a correlated subquery to return one row per customer, representing the customer’s oldest order (the one with the earliest date). Each row should include these three columns: EmailAddress, OrderID, and OrderDate.
I started by joining orders and customers table. EmailAddress is the only column needed from customers table.
SELECT EmailAddress, OrderDate, orderID
FROM Customers c JOIN orders o
ON c.CustomerID = o.CustomerID
A less complicated answer:
SELECT EmailAddress, OrderID, OrderDate AS OldestOrder
FROM Customers AS C
JOIN Orders AS O1
ON C.CustomerID = O1.CustomerID
WHERE O1.OrderDate =
(SELECT MIN(OrderDate)
FROM Orders AS O2
WHERE C.CustomerID = O2.CustomerID)
Use ROW_NUMBER() to get unique ids for each customer which orders by OrderDate in descending order. And the latest date will be RNO=1. Now do the filtration in outer query.
SELECT EmailAddress, OrderDate, orderID
FROM
(
SELECT ROW_NUMBER() OVER(PARTITION BY c.CustomerID ORDER BY OrderDate DESC)RNO,
EmailAddress, OrderDate, orderID
FROM Customers c JOIN orders o
ON c.CustomerID = o.CustomerID
)TAB
WHERE RNO=1
You can still use HAVING Clause and the IN Operator to achieve same results for this particular problem
Code:
SELECT DISTINCT EmailAddress, OrderID, OrderDate
FROM Customers
JOIN orders
ON Customers.CustomerID = Orders.CustomerID
GROUP BY EmailAddress, OrderID, OrderDate
HAVING OrderID IN (1,2,4,5,6,7,8)
ORDER BY EmailAddress ASC;

Getting data from a JOIN in 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.

SQl Query :Joining 4 Tables :One to Many

I have 4 Tables in my SQL server DB:
OrderMaster (OrderId [primaryKey], Orderdate, TotalAmount, SupplierName)
OrderDetails (OrderDetailId[primaryKey], OrderId, Item_Id, Quantity, ManufacturerId)
ItemMaster (Item_Id [primaryKey], ITem Name, ITemCost)
ManufacturerMaster (ManuId[primaryKey], ManufacturerName, HandlingFees)
The Relations are:
OrderDetails table Order id is refering the primary key of OrderMAster table(one to many)
OrderDetails table Item_Id is refering the primary key of ItemMaster
ManufacturerIdtable Order id is refering the primary key of ManufacturerMaster
Orderdetails table can have many records for one record in ORderMaster table.
Now I want to have a query to List all Orders which orderdate=05/01/2009 with the below Items as columns values:
Order number
Total Number of Items (number of child records in orderdetail table) for each order
Total (Sum of) ITemcost for all the items in an order.
How to do the Order by?
select OD.Id, count(IM.Item_Id), sum(IM.ItemCost * OD.ItemQuantity)
from OrderMaster OM
join OrderDetail OD on OD.OrderId = OD.OrderId
join ItemMaster IM on IM.Item_Id = OD.Item_Id
group by OD.OrderId
where OD.OrderDate >= '2009/05/01' and OD.OrderDate < '2009/05/02'
updated per new requirements
Something like this
SELECT
OrderMaster.OrderId,
COUNT(OrderDetailId) as TotalUniqeItems,
SUM(Quantity) as TotalItems,
SUM(ItemCost) as CostofUniqueItems,
(
SELECT ItemCost * Quantity
FROM OrderDetail od
JOIN ItemMaster im ON im.Item_Id = od.Item_Id
WHERE od.Order_Id = OrderMaster.OrderId
) as TotalCost
FROM OrderMaster
JOIN OrderDetail ON OrderMaster.OrderId = OrderDetail.OrderId
JOIN ItemMaster ON ItemMaster.Item_Id = OrderDetail.Item_Id
WHERE OrderDate >= '2009/05/01' AND OrderDate <= '2009/05/02'
I included 2 different ways to get Total Numnber of Items and the cost since I was unsure of the exact desired result.
Note, I did not check my syntax, but this should be close.