Optimising slow SQL query
I am having problem with changing SQL query to preform faster. I need to retrieve the first and th开发者_Go百科e last row for specific time interval. For example I am looking for first and last date that is in the database for some specific time interval (1h, 24h). I have this working sql statment, which I am executing using php:
$query = "
SELECT Date, RainABS
FROM ws3600
WHERE Date IN (
(
SELECT MIN(Date)
FROM ws3600
WHERE Date >= '" . $timeInterval1 . "'
AND Date <= '" . $timeInterval2 . "'
),
(
SELECT MAX(Date)
FROM ws3600
WHERE Date >= '" . $timeInterval1 . "'
AND Date <= '" . $timeInterval2 . "'
)
)
";
As you can see from the query, the table name is ws3600, the parameters I am retrieving are Date and RainABS. I am using the IN operator and two inner select statments.
The problem is, that when executing it:
$result = mysql_query($query);
It takes very long. I measured it using this code:
$mtime = microtime();
$mtime = explode(" ",$mtime);
$mtime = $mtime[1] + $mtime[0];
$starttime = $mtime;
$result = mysql_query($query);
$mtime = microtime();
$mtime = explode(" ",$mtime);
$mtime = $mtime[1] + $mtime[0];
$endtime = $mtime;
$totaltime = ($endtime - $starttime);
And it took on average 0.28s. The problem is that I have to execute 24 of this statments, which accumlates to 6,72s on average. I know I should have probably get rid of the inner selecet statments, but then I don't know how could I get the first and last row?
To get rid of inner selects with MIN or MAX, the answer is often ORDER BY and LIMIT.
Something like this:
SELECT Date, RainABS
FROM ws3600
WHERE Date >= '" . $timeInterval1 . "'
AND Date <= '" . $timeInterval2 . "
ORDER BY Date ASC
LIMIT 1
UNION
SELECT Date, RainABS
FROM ws3600
WHERE Date >= '" . $timeInterval1 . "'
AND Date <= '" . $timeInterval2 . "
ORDER BY Date DESC
LIMIT 1;
This should speed it up, by reducing the number of queries by one.
SELECT Date, RainABS
FROM ws3600
JOIN (
SELECT
MIN(Date) AS min,
MAX(Date) AS max
FROM ws3600
WHERE Date >= '" . $timeInterval1 . "'
AND Date <= '" . $timeInterval2 . "'
) AS x ON (ws3600.Date = min OR ws3600.Date = max);
EDIT: Back by popular demand... I'm leaving my answer here, since it it is "technically" correct, however, I believe the best answer is to use a UNION of two queries, as suggested by Szocske.
精彩评论