开发者

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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜