Ok, this is actually by design.
here we go
* to be able have TOP in a query with relations, you have to have DISTINCT as well.
Explanation:
select TOP 5 c.*
from customers c inner join orders o
on c.customerid = o.customerid
where c.country = 'germany'
this will give 5 duplicate rows, not 5 distinct customers. TOP is therefore useless in this query, or better: it doesn't give proper results. What's needed is DISTINCT, this query therefore gives the proper results:
select DISTINCT TOP 5 c.*
from customers c inner join orders o
on c.customerid = o.customerid
where c.country = 'germany'
The query mechanism switches to client side filtering if DISTINCT and TOP are required but DISTINCT can't be emitted. Though for a SUBquery that's not useful of course, though unavoidable.
- to be able to have DISTINCT in a query which contains an ORDER BY clause, the fields in the ORDER BY clause have to appear in the select list.
Explanation:
this is a requirement for sqlserver (and most other dbs as well, I'm not sure about mysql). Imagine this subquery, which is actually the query generated by my C# snippet above:
(replaced the parameter with hard value, of course '1' was a parameter in the real query)
SELECT [dbo].[Customers].[CustomerID] AS [CustomerId],
[dbo].[Customers].[CompanyName],
[dbo].[Customers].[ContactName],
[dbo].[Customers].[ContactTitle],
[dbo].[Customers].[Address],
[dbo].[Customers].[City],
[dbo].[Customers].[Region],
[dbo].[Customers].[PostalCode],
[dbo].[Customers].[Country],
[dbo].[Customers].[Phone],
[dbo].[Customers].[Fax]
FROM [dbo].[Customers]
WHERE
((
[dbo].[Customers].[CustomerID] IN
(
SELECT [dbo].[Orders].[CustomerID] AS [CustomerId]
FROM ( [dbo].[Orders] INNER JOIN [dbo].[Order Details]
ON [dbo].[Orders].[OrderID]=[dbo].[Order Details].[OrderID])
WHERE [dbo].[Order Details].[ProductID] = 1
ORDER BY [dbo].[Orders].[OrderDate] ASC
)
))
When I modify the subquery to:
SELECT DISTINCT TOP 5 [dbo].[Orders].[CustomerID] AS [CustomerId]
FROM ( [dbo].[Orders] INNER JOIN [dbo].[Order Details]
ON [dbo].[Orders].[OrderID]=[dbo].[Order Details].[OrderID])
WHERE [dbo].[Order Details].[ProductID] = 1
ORDER BY [dbo].[Orders].[OrderDate] ASC
it doesn't work, I get an error:
Server: Msg 145, Level 15, State 1, Line 1
ORDER BY items must appear in the select list if SELECT DISTINCT is specified.
So in other words: it can't be done.