如果未找到任何行,则返回默认值

时间:2013-03-10 05:32:19

标签: mysql select default

我有以下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`

但是,如果没有找到行,它总是返回一个空结果。我该如何返回默认值?

3 个答案:

答案 0 :(得分:22)

一种方法

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 :(得分:7)

对于只需要一行结果的情况,只需在第二个UNION子句中使用带有硬编码值的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使用相同的列(按相同顺序),则不必为第二个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;

我的意见是,这很容易阅读,并且看起来不像是一个有问题的查询。

答案 2 :(得分: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