I wonder why you have this complex ORDER BY
. I think this is enough:
SELECT Id, Price
FROM tblStock
WHERE AddDate >= date_sub(curdate(), interval 10 day)
ORDER BY Price ASC
LIMIT 50 ;
The real problem is how to optimize this. Since it has one range condition (on column (AddDate)
in the WHERE
clause and an ordering by a different column (Price
), it is really hard.
You may get some efficiency improvement with an index on (Price, AddDate, Id)
but it's really a shot in the dark. It will sometimes work fast (when many rows with lowest prices have current dates, too) and it will be totally inefficient other times (when the rows with lowest prices have mostly older dates so almost all or all the index will have to be scanned until 50 matches are found.)
I had asked a question about an almost identical query a few months ago and @Jack Douglas has provided a wonderful solution while @Erwin Brandstetter improved it further: : Can spatial index help a “range - order by - limit” query
It's for Postgres but I think it can be modified to work in MySQL.
The NULLS LAST
issue is not the main problem as I see it. It can be solved with a UNION
:
( SELECT Id, Price, 1 AS Ord
FROM tblStock
WHERE AddDate >= date_sub(curdate(), interval 10 day)
AND Price >= 0
ORDER BY Price ASC
LIMIT 50
)
UNION ALL
( SELECT Id, Price, 2
FROM tblStock
WHERE AddDate >= date_sub(curdate(), interval 10 day)
AND Price IS NULL
-- ORDER BY Price ASC
LIMIT 50
(
ORDER BY Ord, Price
LIMIT 50 ;
and while the 2nd part will be efficient (using a (Price, AddDate, Id)
index), the 1st part has the same issues as your query and my other proposal.