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

相关问题