SQL Server 2012 Query Confusion - sql-server-2012

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;

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

Distinct one column on two tables SQL Server 2008

I have two different tables and I want to use distinct on only one column. I want to get recent records only. what query should I write in SQL Server 2008? I want to use distinct one only CustomerID not any other column.
Table1: Customer
Columns: CustomerID, CustomerName
Table2: Order
Columns: OrderID, CustomerID, OrderName
I tried two SQL queries both not working
First query
select Distinct on (CustomerID) CustomerID, CustomerName, OrderID, OrderName
from Customer
left join Order on Customer.CustomerID = Order.CustomerID
Second query:
select Max(Distinct ID)
CustomerID, CustomerName, OrderID, OrderName
from
Customer
left join
Order on Customer.CustomerID = Order.CustomerID
Assuming the higher OrderID is latest, this should work if I understand your requirement righly:
select
c.CustomerID,
c.CustomerName,
o.OrderID,
o.OrderName
from Customer as c
inner join (select
CustomerID,
max(update_date) as max_update_date
from Customer
group by CustomerID) as mc
on mc.CustomerID = c.CustomerID
and mc.max_update_date = c.update_date
inner join Order as o
on o.CustomerID = c.CustomerID
inner join (select
CustomerID,
max(OrderID) as max_OrderID
from Order
group by CustomerID) as m
on m.CustomerID = c.CustomerID
and m.max_OrderID = o.OrderID

Compare a table with a count result from another table and add the names that have a zero count

I am counting how many times a company has ordered. Then I am only showing if a company has ordered less than 5 times. I am then checking it against the table with all company names to see what company has not ordered, which would not show up on the order table, then add their name on the displayed list.
What I have tried:
Select Orders.CustomerID, Count(Orders.CustomerID) AS OrderCount
From Orders Left Join Customers
On Orders.CustomerID = Customers.CustomerID
Group By Orders.CustomerID
Having Count(Orders.CustomerID) <5
This is totally wrong:
Select CustomerID
From Customers
Where EXISTS
(Select CustomerID, Count(CustomerID) AS 'OrderCount'
From Orders
Group BY CustomerID
Having Count(Orders.CustomerID) < 5)
I need to somehow compare the list of names before I ask it to see which ones have ordered less than 5 times.
Thanks
If you want to use LEFT JOIN, interchange the table names since you want to show values from Customers, otherwise use RIGHT JOIN instead.
SELECT Customers.CustomerID,
COUNT(Orders.CustomerID) AS OrderCount
FROM Customers
LEFT JOIN Orders
ON Orders.CustomerID = Customers.CustomerID
GROUP BY Customers.CustomerID
HAVING COUNT(Orders.CustomerID) < 5
using EXISTS()
SELECT CustomerID
FROM Customers c
WHERE EXISTS
(
SELECT 1
FROM Orders o
WHERE o.CustomerID = c.CustomerID
GROUP BY CustomerID
HAVING COUNT(CustomerID) < 5
)
Try this:
SELECT C.CustomerID, C.CustomerName, COUNT(O.CustomerID) AS OrderCount
FROM Customers C
LEFT JOIN Orders O ON O.CustomerID = C.CustomerID
GROUP BY C.CustomerID
HAVING OrderCount < 5
ORDER BY OrderCount, C.CustomerName

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;