2015-10-09 37 views
0

我有一個腳本根據請求的日期搜索某些值。Mysql:如果搜索條件不符合,查詢是否可以返回最後一個條目?

SELECT `entry_value` FROM `data` WHERE (`entry_year` = $year AND `entry_month` = $month) LIMIT 1; 

現在,問題是,當用戶輸入太近的日期並且沒有找到任何值時,我想要獲取最近的可用條目。

我知道如何檢索最後一個條目,並且我可以使用第一個調用來首先檢查最後一個可用日期是什麼,並且調用上面的查詢或另一個查詢以獲取最後一個值,如果請求的不是可用。 只是想知道,但有沒有辦法直接問到mysql?我不會寫代碼,因爲我沒有那種結構使用的想法,但理想的邏輯是這樣的:

SELECT `entry_value` FROM `data` 
WHERE (`entry_year` = $year AND `entry_month` = $month) 
OR_IF_NOT_FOUND WHERE MAX(`id`) 
LIMIT 1; 

是否有類似的東西在MySQL的?

親切的問候

回答

1

方法1

您可以運行查詢,隨後在同一順序相同的字段,使用UNION 「默認」 查詢。

SELECT ...query1... 
UNION 
SELECT * FROM (SELECT ... LIMIT 1) AS defaults; 

這將始終運行第一查詢第二查詢,總是會返回比單獨第一查詢將一個結果了。這取決於你,然後放棄最後的結果。

另一種可能性是以相反的順序進行。現在的「空」的結果首先返回:

SELECT * FROM (SELECT ... LIMIT 1) AS defaults; 
UNION 
SELECT ...query1... 

這樣你就可以提取一個元組,再下去就好像你單獨運行第一個查詢。

方法2

在某些情況下,你可以建立與結果優先順序。例如:

SELECT `entry_value` FROM `data` WHERE (`entry_year` = $year AND 
`entry_month` = $month) LIMIT 1; 

可能成爲:

SELECT `entry_value` FROM `data` ORDER BY 
    (`entry_year` = $year AND `entry_month` = $month) DESC, 
    `entry_year` = $year DESC, 
    ABS(`entry_year` - $year)*12 + ABS(`entry_month` - $month) 
LIMIT 1; 

這將檢索的所有數據,並且(entry_year = $year AND entry_month = $month)可以爲真(1)或假(0)。 DESC命令將使它成爲第一行將是完美匹配的那一行。

同樣,在不匹配的行中,如果它存在,則隨機選擇一個與正確年份相同的行。但是如果所需年份中完全沒有數據,則將選擇具有最短時間距離的行。

此方法強烈建議在使用的字段(年和月)上有一個索引,並將掃描所有記錄。所以它可能相當昂貴。

方法3

性能方面,方法1是幾乎同樣的事情,同時運行的查詢,因此,如果可能的話,你寧願做明確的,是這樣的:

// CODE BEFORE MODIFICATION (ran 1 query) 
$query = "SELECT..."; 
// Execute query 

foreach ($tuple = SQLFetch($handle)) { 
    // ...do something with data 
} 



// CODE AFTER (2 queries - or any number, actually) 

$queries = [     
    "SELECT ...", 
    "SELECT ... LIMIT 1", 
]; 
foreach ($queries as $query) { 
    // $query = 
    // Execute $query 
    foreach ($tuple = SQLFetch($handle)) { 
     // ...do something with data 
    } 
    if (SQLNumRows($handle) > 0) { 
     break; 
    } 
} 

正如你可以看到,舊代碼實際上保持不變,並且額外的查詢(或多個查詢)僅在其之前的查詢沒有返回任何內容時才被執行。獲取元組和取回元組數的實際指令取決於您使用的實際數據庫接口。

0

http://sqlfiddle.com/#!9/437374/5

SELECT 
    COALESCE(d1.id,d.id) id, 
    COALESCE(d1.entry_value,d.entry_value) entry_value 
FROM `data` d 
LEFT JOIN `data` d1 
ON d1.entry_year = $year 
    AND d1.entry_month = $month 
ORDER BY d.id DESC 
LIMIT 1; 
0

我認爲這可能爲你工作:

SELECT `entry_value` FROM `data` WHERE 
(`entry_year` = $year AND `entry_month` = $month) 
OR 
(`entry_year` = $most_recent_year AND `entry_month` = $most_recent_month) 
LIMIT 1; 
相關問題