Reputation: 13
i have a database containing:
Customerno, No_, Quantity
i would like to return a TOP 10 Most sold products per customer in one go...
i can get a TOP 10 like this:
SELECT TOP 10 [No_],sum([Quantity]) as antal
FROM orderlines
WHERE [Gen_ Prod_ Posting Group] = 'HANDEL'
AND [Customerno] = 10001
GROUP BY [No_]
HAVING sum([Quantity]) >= 2
ORDER BY sum([Quantity]) DESC
but i need some kind of "foreach" because the above query is limited to customer: 10001
i would like it to loop foreach distinct customerno, so i recieve a total list
the easy way i know is to make an
SQL query in PHP like this:
while($row = myssql_fetch_array(mssql_query(SELECT DISTINCT Customerno FROM orderlines)))
{
$new_query = ("SELECT TOP 10 [No_],sum([Quantity]) as antal
FROM orderlines
WHERE [Customerno] = $row['customerno']
GROUP BY [No_]
HAVING sum([Quantity]) >= 2
ORDER BY sum([Quantity]) DESC");
}
but i feel it should be more efficient to do directly in SQL ?
Upvotes: 0
Views: 50
Reputation: 1270653
The canonical method uses row_number()
:
SELECT cn.CustomerNo, cn.[No_], cn.antal
FROM (SELECT CustomerNo, [No_], SUM(Quantity) as antal,
ROW_NUMBER() OVER (PARTITION BY CustomerNo ORDER BY SUM(Quantity) DESC) as seqnum
FROM orderlines ol
WHERE Gen_ Prod_ Posting Group = 'HANDEL'
GROUP BY CustomerNo, [No_]
) cn
WHERE seqnum <= 10
ORDER BY CusterNo, antal DESC;
I removed the HAVING
condition because that is not part of your problem statement. Obviously, you can filter this based on some minimum antal
.
Upvotes: 1
Reputation: 176004
Canonical way is to use ROW_NUMBER
. But you could use OUTER APPLY
to simulate For-each
:
SELECT DISTINCT Customerno, sub.*
FROM orderlines o
OUTER APPLY (SELECT TOP 10 [No_],sum([Quantity]) as antal
FROM orderlines o2
WHERE [Gen_ Prod_ Posting Group] = 'HANDEL'
AND o.Customerno = o2.Customerno
GROUP BY [No_]
HAVING sum([Quantity]) >= 2
ORDER BY antal DESC
) AS sub
ORDER BY Customerno, sub.antal DESC
Upvotes: 0