8

我需要从第二个表中查询数据,但前提是满足主表中的一组罕见条件:

SELECT ..., IF(a AND b AND c AND (SELECT 1 FROM tableb ...)) FROM tablea ...

a、b 和 c 条件几乎总是错误的,所以我的想法是子查询永远不会对结果集中的大多数行执行,因此比连接快得多。但这只有在 IF() 语句短路时才会成立。

可以?

感谢你们提供的任何帮助。

4

4 回答 4

10

答案是肯定的。
mysql 查询中的 IF(cond,expr_true,expr_false) 短路。

这里有一个测试,使用@variables 来证明这个事实:

SET @var:=5;  
SELECT IF(1 = 0, (@var:=@var + 1), @var ); -- using ':=' operator to modify 'true' expr @var 
SELECT IF(1 = 1, @var, (@var:=@var + 1) ); -- using ':=' operator to modify 'false' expr @var 
SELECT @var;

所有三个 SELECT 查询的结果都是“5”。

如果 IF() 函数没有短路,结果将是来自 SELECT #1 的“5”,来自 SELECT #2 的“6”,以及来自最后一个“select @var”的“7”。

这是因为在选择 #1 中永远不会执行“真”表达式,也不会为选择 #2 执行假表达式。

请注意,':=' 运算符用于在 SQL 查询(select、from 和 where 子句)中修改 @var。你可以从中得到一些非常花哨/复杂的 SQL。我使用@vars 在 SQL 查询中应用“过程”逻辑。

-- 乔根森 --

于 2010-09-21T18:50:37.030 回答
2

在 J. Jorgenson 的帮助下,我提出了自己的测试用例。他的示例并没有尝试在条件评估中进行短路,但是使用他的想法,我提出了自己的测试并验证了 MySQL 确实短路了 IF() 条件检查。

SET @var:=5;
SELECT IF(1 = 0 AND (@var:=10), 123, @var); #Expected output: 5
SELECT IF(1 = 1 AND (@var:=10), @var, 123); #Expected output: 10

在第二个示例中,MySQL 正确地短路了:@var 永远不会设置为 10。

感谢 J. Jorgenson 的帮助!

于 2010-09-22T13:56:01.197 回答
0

在 SQL 分析器中试一试。如果您想安全起见并且不必相信数据库以一种方式工作(并且不要在新版本中改变这种行为),只需进行两次查询并以编程方式执行 IF。

于 2010-09-14T21:38:39.257 回答
0

这取决于。

IF 不会短路,因此它可用于避免 GROUP_CONCAT 的截断警告,例如:

set @@group_concat_max_len = 5;

select if(true or @var:=group_concat('warns if evaluated'), 'actual result', @var);

结果将是“实际结果”,但您会收到警告:

Warning (Code 1260): Row 1 was cut by GROUP_CONCAT()

这与使用不那么琐碎的 GROUP_CONCAT 表达式(例如不同的键)以及根本没有 IF 的情况下得到的警告相同。

于 2014-07-24T23:38:54.430 回答