2013-03-10 82 views
15

我有以下select語句來獲取流的下一個計劃項目。如果沒有匹配的行,我希望它返回一個默認值。下面是我使用的線:如果未找到行,則返回默認值

SELECT `file` FROM `show`, `schedule` 
    WHERE `channel` = 1 AND `start_time` <= UNIX_TIMESTAMP() 
    AND `start_time` > UNIX_TIMESTAMP()-1800 AND `show`.`id` = `schedule`.`file` 
    ORDER BY `start_time` DESC LIMIT 1 

這應該抓住最近預約內容,但如果查詢前年長超過30分鐘沒有。但是,如果用戶沒有計劃任何事情,我需要一個默認值,以便在流上實際播放某些內容。我已經試過如下:

SELECT COALESCE(`file`, 'default.webm') FROM `show`, `schedule`... 

和:

SELECT IFNULL(`file`, 'default.webm') FROM `show`, `schedule` 

然而,如果沒有行被發現總是返回一個空的結果。我怎樣才能返回一個默認值呢?

回答

20

一種方式做到這一點

SELECT IFNULL(MIN(`file`), 'default.webm') `file` 
    FROM `show`, `schedule` 
WHERE `channel` = 1 AND `start_time` <= UNIX_TIMESTAMP() 
    AND `start_time` > UNIX_TIMESTAMP()-1800 AND `show`.`id` = `schedule`.`file` 
ORDER BY `start_time` DESC LIMIT 1 

既然你只返回一行,您可以使用一個聚合函數,在這種情況下MIN(),確保,如果選擇沒有記錄,你會得到NULL。然後IFNULL()COALESCE()將完成其工作。

+1

輝煌的東西!但是,如何將這個概念應用於返回多行而不是一個查詢的查詢? – Vectoria 2015-07-16 13:47:17

+0

這不是一個很好的解決方案,正如Tomas在下面解釋的那樣(除非您查詢主鍵值)。 – Pierre 2015-10-18 07:39:33

0

要處理更多種情況,您需要一些條件邏輯。這僅僅是在MySQL存儲過程中可用,因此你需要在過程中包裝該代碼,並稱之爲:

if exists (
     SELECT `file` FROM `show`, `schedule` 
     WHERE `channel` = 1 AND `start_time` <= UNIX_TIMESTAMP() 
     AND `start_time` > UNIX_TIMESTAMP()-1800 AND `show`.`id` = `schedule`.`file` 
) then 
     SELECT `file` FROM `show`, `schedule` 
     WHERE `channel` = 1 AND `start_time` <= UNIX_TIMESTAMP() 
     AND `start_time` > UNIX_TIMESTAMP()-1800 AND `show`.`id` = `schedule`.`file` 
     ORDER BY `start_time` DESC LIMIT 1 
; else 
     select `DefaultValue` as `file` 
; end if 
7

對於那些結果只有一行預期的情況下,只需使用UNION用硬編碼值( s)在第二個SELECT子句中具有與原始SELECT相同的列數。

對於OP:

(SELECT `file` FROM `show`, `schedule` 
    WHERE `channel` = 1 AND `start_time` <= UNIX_TIMESTAMP() 
    AND `start_time` > UNIX_TIMESTAMP()-1800 AND `show`.`id` = `schedule`.`file` 
    ORDER BY `start_time` DESC LIMIT 1) UNION (SELECT 'default.webm') LIMIT 1; 

除非任何語法錯誤,結果集將成爲移動一行與所謂file一列。


作爲更一般的例子:

(SELECT Col1,Col2,Col3 FROM ExampleTable WHERE ID='1234') 
UNION (SELECT 'Def Val','none','') LIMIT 1; 

在任一情況:

  • 如果沒有在所述第一SELECT發現行,結果集將被填充有來自第二個SELECT的值。

  • 如果在第一個SELECT中找到一行,則會在結果集中提供第一個SELECT值,並省略第二個SELECT值。

*你,如果你想從第一個SELECT使用相同的列(以相同的順序)沒有列名/別名分配給第二選擇值。

* UNION不要求來自兩個聯合查詢的列名是相同的,事實上,如果它有助於您的情況,您可以將不同的列名分配給第二個SELECT查詢。 (您的結果集處理代碼將需要適應這些列命名差異。)

(SELECT Col1,Col2,Col3 FROM ExampleTable WHERE ID='1234') 
UNION (SELECT 'Def Val' AS `Fallback1`,'none' AS `Fallback2`,'' AS `Fallback3`) LIMIT 1; 

我的意見是,這是很容易閱讀,似乎並不像徵稅查詢。

+0

這對我來說非常好。我需要用一個謂詞來進行聚集('MAX'),如果沒有與謂詞相匹配的行,我就不會返回行。現在我得到默認回來。 – Rob 2017-01-04 18:39:33

相關問題