Distinct one column on two tables SQL Server 2008 - sql

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

Related

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;

SQL Query to return the Top 2 Values

I am trying to return the top 2 most ordered items in our customer database. Below is what I have for the most ordered item but I am having trouble figuring out how to create another column for the 2nd most ordered item.
What is the best way to create the 2nd column?
SELECT FirstName, EmailAddress, Id, PreferredLocationId,
(
SELECT TOP 1 [Description] FROM [Order] o
INNER JOIN [OrderItem] oi ON oi.OrderId = o.OrderId
WHERE o.CustomerId = Customer.Id
GROUP BY [Description]
ORDER BY COUNT(*) DESC
) AS MostOrderedItem
FROM Customer
GROUP BY FirstName, EmailAddress, Id, PreferredLocationId
Lot's of different ways to handle this if you're using SQL Server 2012. I'm going to use a CTE to get the first two rows and use ROW_NUMBER()
WITH cte AS (
SELECT CustomerId, [Description]
, ROW_NUMBER() OVER (PARTITION BY CustomerId ORDER BY COUNT(*) DESC) [RowID]
FROM [Order] o
INNER JOIN [OrderItem] oi ON oi.OrderId = o.OrderId
GROUP BY CustomerId, [Description]
)
SELECT FirstName, EmailAddress, Id, PreferredLocationId, cte1.Description, cte2.Description
FROM Customer
LEFT JOIN cte cte1 ON cte1.CustomerID = Customer.CustomerId AND cte1.RowID = 1
LEFT JOIN cte cte2 ON cte2.CustomerID = Customer.CustomerId AND cte2.RowID = 2
The Common Table Expression creates the list of all customers, descriptions and their row number. Note that if you have ties, you're not guarunteed which description will come first. You can add to to the windowing function description so that if there is a tie, whatever comes first in the alphabet will be the tie breaker.

Need to order output based on date - Sub query

I have a simple subquery where I have two tables. First table has the customer id, first name and last name. Second table has the customer id and order date. I want to generate a query that shows the first name, last name and order date.
I have tried the below code and i dont know how the order the output based on date
Select
Customerid,
FirstName,
LastName
From
Customer
Where
CustomerID IN (select
CustomerID
from
orders
where
orderdate is not null);
The output I show is only the customer id, first name and last name. How do I include the order date in my output.
what did u select = what will display for you, include date in your select statement
Select A.Customerid, A.firstname, A.lastname, B.orderdate
From tableA A
Inner join Tableb B on A.customerid = B.customerid
For your modified question(s), try query below
Select A.firstname, A.lastname, B.orderdate
From tableA A
Inner join Tableb B on A.customerid = B.customerid
Order By B.orederdate
;with CustomerProductOrderOrdinal( OrderId, Ordinal )
as
(
select
o.OrderId
, row_number() over ( partition by o.CustomerId, o.ProductId order by o.OrderDate ) Ordinal
from
Orders o
where
o.OrderDate is not null
-- filter for product here if so desired
-- and o.ProductId = <whatever>
)
,FirstCustomerProductOrder( OrderId )
as
(
select
OrderId
from
CustomerProductOrderOrdinal
where
Ordinal = 1
)
select
c.CustomerId
, c.FirstName
, c.LastName
--, p.ProductId
, o.OrderDate
From
Customer c
inner join Orders o
on c.CustomerId = o.CustomerId
inner join FirstCustomerProductOrder fcpo
on o.OrderId = fcpo.OrderId
-- join with product if you want product info
--inner join Product p
-- on o.ProductId = p.ProductId

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;

SQL - confused with aggregate

I currently have this query:
select
customers.emailaddress,
MAX(orders.orderdate) as "last order"
from orders
join customers
on orders.customerID = customers.customerID
group by customers.emailaddress
Which gives me the emails, and the last order date. With the 'Orders' table, there is a field named 'PaymentTotal', how can I get this based on the value returned by MAX(orders.orderdate)? (ie am trying to get the amount of the last order per email)
select c.EmailAddress, om.MaxOrderDate, o.PaymentTotal
from (
select CustomerID, MAX(orders.orderdate) as MaxOrderDate
from orders
group by CustomerID
) om
inner join orders o on om.CustomerID = o.CustomerID
and om.MaxOrderDate = o.orderdate
inner join customers c on o.customerID = c.customerID