我有以下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`
但是,如果没有找到行,它总是返回一个空结果。我该如何返回默认值?
答案 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