Author |
Topic |
coolerbob
Aged Yak Warrior
841 Posts |
Posted - 2007-09-25 : 10:52:37
|
Why do this?SELECT C.customerid, city, orderidFROM dbo.Customers AS C CROSS APPLY (SELECT TOP(2) orderid, customerid FROM dbo.Orders AS O WHERE O.customerid = C.customerid ORDER BY orderid DESC) AS CAWhen you can do this?SELECT C.customerid, city, orderidFROM dbo.Customers AS Cjoin (SELECT TOP(2) orderid, customerid FROM dbo.Orders ORDER BY orderid DESC) AS CA on CA.customerid=C.customerid |
|
jsmith8858
Dr. Cross Join
7423 Posts |
Posted - 2007-09-25 : 10:58:14
|
Because they are not the same? The second will only return results for (at most) two customers, based on the last two orders (ordered by OrderID DESC). Try it.Better is to simply use ROWNUMBER() or RANK() over OrderID and filter where they are <= 2.- Jeffhttp://weblogs.sqlteam.com/JeffS |
|
|
coolerbob
Aged Yak Warrior
841 Posts |
Posted - 2007-09-25 : 11:01:18
|
quote: Originally posted by jsmith8858 The second will only return results for (at most) two customers
That's the same for CROSS APPLY too isn't it?Aren't you thinking of OUTER APPLY? |
|
|
jsmith8858
Dr. Cross Join
7423 Posts |
|
jsmith8858
Dr. Cross Join
7423 Posts |
Posted - 2007-09-25 : 11:07:34
|
Here they are, using Adventure Works:SELECT C.CustomerID, C.CustomerType, CA.SalesOrderIDFROM Sales.Customer AS CCROSS APPLY(SELECT TOP 2 O.SalesOrderID, O.CustomerIDFROM Sales.SalesOrderHeader AS OWHERE O.CustomerID = C.CustomerIDORDER BY SalesOrderID DESC) AS CASELECT C.CustomerID, C.CustomerType, CA.SalesOrderIDFROM Sales.Customer AS CINNER JOIN(SELECT TOP 2 O.SalesOrderID, O.CustomerIDFROM Sales.SalesOrderHeader AS OORDER BY SalesOrderID DESC) AS CA on CA.CustomerID = C.CustomerIDnotice the results returned ...- Jeffhttp://weblogs.sqlteam.com/JeffS |
|
|
jsmith8858
Dr. Cross Join
7423 Posts |
Posted - 2007-09-25 : 11:11:00
|
And here's the ROW_NUMBER version (same results as CROSS APPLY)SELECT x.* FROM(SELECT C.CustomerID, C.CustomerType, O.SalesOrderID, ROW_NUMBER() OVER (PARTITION BY C.CustomerID ORDER BY O.SalesOrderID DESC) as [Rank]FROM Sales.Customer AS CINNER JOIN Sales.SalesOrderHeader AS O on C.CustomerID = O.CustomerID) xwhere x.Rank <=2- Jeffhttp://weblogs.sqlteam.com/JeffS |
|
|
coolerbob
Aged Yak Warrior
841 Posts |
Posted - 2007-09-25 : 11:29:11
|
I temporarily didn't have access to Management Studio so couldn't test it. I have now and I see your point.So could you accomplish the same output as:SELECT C.CustomerID, C.CustomerType, CA.SalesOrderIDFROM Sales.Customer AS CCROSS APPLY(SELECT TOP 2 O.SalesOrderID, O.CustomerIDFROM Sales.SalesOrderHeader AS OWHERE O.CustomerID = C.CustomerIDORDER BY SalesOrderID DESC) AS CAwithout using the APPLY table operator or ROW_NUMBER? Just old-school set-based querying (without loops, #temp tables etc)? |
|
|
jsmith8858
Dr. Cross Join
7423 Posts |
Posted - 2007-09-25 : 11:38:29
|
Yes, but it will not be as efficient. either something like this:select customer.customerID, orders.orderID, from customersinner join orders on customers.customerID = orders.customerIDwhere orderID in (select top 2 orderID from orders where orders.customerID = customers.CustomerID order by orderID DESC)or by calculating the rank/row number manually like this:select * from(select customer.customerID, orders.orderID, (select count(*) from orders o2 where o2.orderID >= orders.orderID and o2.customerID = customer.CustomerID) as Rankfrom customersinner join orders on customers.customerID = orders.customerID) rwhere r.Rank <= 2more here: http://weblogs.sqlteam.com/jeffs/archive/2007/03/28/60146.aspx- Jeffhttp://weblogs.sqlteam.com/JeffS |
|
|
coolerbob
Aged Yak Warrior
841 Posts |
Posted - 2007-09-25 : 11:48:38
|
That's brilliant thanks. |
|
|
|