I have been using stackoverflow vastly during the last year – an excellent source w/ great contributors. Now it’s my time to request for help.
The setup is normal:
Orders, OrderArticles and Articles
I want to get the total amount of articles sold during the last year, but only during the best 5 weeks.
Never mind the WEEK-function and UNIXTIME-blah blah – I’ve got that covered. My question is wether it’s possible or not to do without resorting to stored procedures or functions.
I have created a subquery for the summary for each week and article and order the result by the sum descendingly. Now – I only have to LIMIT the query to 5. Easy, but I also have to filter the result on the ArticleID BUT since I’m inside a subquery I don’t have access to the outer ArticleID and it doesn’t help to JOIN the result – it’s too late 😉
The syntax (hard to understand w/o the actual sql, right…?)
SELECT a.ID, [more fields], omg.total
FROM Articles AS a
LEFT JOIN
(
SELECT weeklytotals.articleID, weeklytotals.total
FROM
(
SELECT SUM(ra.quantity) AS total, ra.articleID AS articleID
FROM OrderArticles ra
INNER JOIN Orders r
ON ra.orderID = r.ID
WHERE r.timeCreated >= UNIX_TIMESTAMP('2011-06-30')
GROUP BY ra.articleID, WEEK(FROM_UNIXTIME(r.timeCreated))
ORDER BY SUM(ra.quantity) DESC
) AS weeklytotals
WHERE omg.articleID = a.ID --<-- THIS IS NOT WORKING BUT NECESSARY!
LIMIT 0, 5
) AS omg
ON omg.articleID = a.ID
WHERE a.isEnabled = 1 --more WHERE-thingys
This here returns the top 5 articles and ties the them to the correct Article. yay.
I have left out the SUM-function (which could go into the omg-SELECT).
Do you understand? Do I understand what I want? Yes, of course we do!
Thanx in advance.
Edit: The conditions have been changed – which makes my life easier, but I still would like to know if there is a solution to the problem.
If you require the
omgsubquery to use data from theatable, place it into theSELECTpart not theFROMpart. Using terms from the mysql documentation, you want the result of a correlated subquery to appear as a scalar operand in the outer result set.You wrote about being interested in the sum, i.e. only a single number per article, although you left out the
SUMfrom your example query. My approach relies on that sum, and would probably break in a bad way if you really needed distinct values for each of the best five weeks.I’m not saying anything about performance here. Placing the subquery this way, it will be executed for every row of the result set. So it might be too slow for practical use if you have a large number of articles. But if that should happen, I doubt that stored procedures or similar tricks would fare any better.
Edit: I found out that my original suggestion, which used subquerys nested two levels deep, doesn’t allow access the innermost subquery to use a column of the outermost. But toying with this on sqlfiddle I also found out that one may safely pass the result of a subquery to sum, thus avoiding one level of nesting. So the above code nos has actually been checked and executed by a MySQL server, and should therefore work as intended.