@peterm 的答案和这个答案旨在适应 SQL 逻辑,该逻辑将在结果集中返回最多一行。
他的答案旨在返回单行和单列。
我的答案旨在返回包含一列或多列的单行。
本质上,您可以UNION
在第二个子句中使用硬编码值,该SELECT
子句与第一个 SELECT 具有相同的列数。
对于 OP:
(
SELECT `file`
FROM `show`,
`schedule`
WHERE `channel` = 1
AND `start_time` BETWEEN UNIX_TIMESTAMP()-1799 AND UNIX_TIMESTAMP()
AND `show`.`id` = `schedule`.`file`
ORDER BY `start_time` DESC
LIMIT 1
) UNION (
SELECT 'default.webm'
)
ORDER BY file = 'default.webm'
LIMIT 1;
除非出现任何语法错误,否则结果集将提供一行,其中一列键为file
.
作为一个更一般的例子:(DB-Fiddle Demo)
(
SELECT Col1,Col2,Col3
FROM ExampleTable
WHERE ID='1234'
) UNION (
SELECT 'Def Val','none',''
)
ORDER BY Col1 = 'Def Val'
LIMIT 1;
结果:
如果在第一个 SELECT 中没有找到任何行,则结果集将填充第二个 SELECT 中的值。作为数组的结果集将是:
[['Col1' => 'Def Val', 'Col2' => 'none', 'Col3' => '']]
如果在第一个 SELECT 中找到一行,则在结果集中提供第一个 SELECT 值,而省略第二个 SELECT 值。结果集将是:(请参阅我的演示链接)
[['Col1' => 'A', 'Col2' => 'B', 'Col3' => 'C']]
*结果集中的关联键将由第一个 SELECT 查询中的列名/别名决定。
*后续的 SELECT 查询不需要指定列别名。
*UNION 不要求来自两个联合查询的列名相同。事实上,后续 SELECT 查询中的列名或数据源可能是任何东西(不同的列、函数调用等)。
(
SELECT Col1,Col2,Col3
FROM ExampleTable
WHERE ID='1234'
) UNION (
SELECT 'Def Val' AS `Fallback1`,
'none' AS `Fallback2`,
'' AS `Fallback3`
)
ORDER BY Col1 = 'Def Val'
LIMIT 1;
我的观点是,这很容易阅读,而且看起来不像是一个繁重的查询。
感谢@LudovicKuty 发现了一个关于 UNION 生成的行顺序的潜在错误。https://dev.mysql.com/doc/refman/8.0/en/union.html#union-order-by-limit要消除默认行在找到的行之前排序的可能性,请编写一个 ORDER BY 子句足够的逻辑来确保默认行总是在结果集中的后面排序。将有不同的 sql-dialect-specific 语法可用于识别默认行。在某些ORDER BY columnName = 'default value'
情况下就足够了,其他人可能会要求IF
or IIF
orCASE
等。只要您构建逻辑以便默认返回一个真实的结果,那么 true 将被视为1
并且 false 将被视为0
- 当然1
是在之后0
升序排序时。