When you don't have subselects, you have two options: temporary tables or JOINed queries.In your case, I think the temporary table is the better way to go.
I would also eliminate the ABS() check so that I can compare values directly against the index. I know the math is correct your way but this way you are comparing values directly against the column which means that indexes can come into play. SET @targetLat = 44.6, @targetLon = -123.8, @Delta = 3 CREATE TEMPORARY TABLE tmpDeltaData SELECT city, state, country, latitude, longitude FROM Londata WHERE latitude BETWEEN (@[EMAIL PROTECTED]) AND (@targetLat + @Delta) AND longitude BETWEEN (@targetLon - @Delta) AND (@targetLon + @Delta) SELECT city, state, country, latitude, longitude, IF(latitude REGEXP '[0-9\\.]+$' AND longitude REGEXP'[0-9\\.]+$', ROUND(DEGREES(ACOS((SIN(RADIANS(@targetLat))) * (SIN(RADIANS(latitude))) + (COS(RADIANS(@targetLat))) * (COS(RADIANS(latitude))) * (COS(RADIANS(@targetLon -longitude))))) * 111),99999999) as distance FROM tmpDeltaData ORDER BY distance DROP TEMPORARY TABLE tmpDeltaData I would also test the WHERE clause from tmpDeltaData with your original query to compare speeds of the two methods. Shawn Green Database Administrator Unimin Corporation - Spruce Pine Gerald Taylor <[EMAIL PROTECTED]> wrote on 10/04/2004 10:33:22 AM: > Query optimization question > > I am selecting from a single table but it has a lot of rows and it has > a very involved calculation. What I really want to do is > is FIRST restrict the number of rows so that the big calculation is only > performed on the ones that are within 3 degrees. > > Using 4.0.20 > > A sample query is given here: > The application interpolates variable values such as 44.6 into > the query string, so from mysql's > point of view they are constants, right? And the explain doc > says it optimizes constants, but it is looking at all the rows > and I see why. > > SELECT city, state, country, latitude, longitude, > IF(latitude REGEXP '[0-9]+$' AND longitude REGEXP'[0-9]+$', > ROUND(DEGREES(ACOS((SIN(RADIANS(44.6))) * > (SIN(RADIANS(latitude))) + > (COS(RADIANS(44.6))) * > (COS(RADIANS(latitude))) * > (COS(RADIANS(-123.28 -longitude))))) > * 111),99999999) as distance FROM londata > WHERE ABS(44.6-latitude) <= 3.0 AND ABS(-123.28-longitude) <= 3.0 ORDER > BY distance; > > > I guess I can't do a subselect with my version... > If I could what would it look like? > Something like below? (I might be able to talk > the powers that be into an upgrade.) And if I can't > is it more horrible to manually create a temporary table > and perform the calculations on it than it is to > just do what I am doing? > > SELECT city, state, country, latitude, longitude, > IF(latitude REGEXP '[0-9]+$' AND longitude REGEXP'[0-9]+$', > ROUND(DEGREES(ACOS((SIN(RADIANS(44.6))) * > (SIN(RADIANS(latitude))) + > (COS(RADIANS(44.6))) * > (COS(RADIANS(latitude))) * > (COS(RADIANS(-123.28 -longitude))))) > * 111),99999999) as distance FROM (SELECT * FROM londata > WHERE ABS(44.6-latitude) <= 3.0 AND ABS(-123.28-longitude) <= 3.0) > as > sublon ORDER BY distance; > > Thanks. > > GT > > > -- > MySQL General Mailing List > For list archives: http://lists.mysql.com/mysql > To unsubscribe: http://lists.mysql.com/[EMAIL PROTECTED] >