我需要查询第二个表中的数据,但前提是满足主表中一组罕见的条件:
SELECT ..., IF(a AND b AND c AND (SELECT 1 FROM tableb ...)) FROM tablea ...
a,b和c条件几乎总是假的,所以我的想法是子查询永远不会对结果集中的大多数行执行,因此比连接更快。但只有当IF()语句短路时才会这样。
是吗?
感谢您提供任何帮助。
答案 0 :(得分:8)
答案是肯定的 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'。
这是因为'true'表达式永远不会执行,在select#1中,也不是为select#2执行的false表达式。
注意':='运算符用于在SQL查询(select,from和where子句)中修改@var。你可以从中获得一些非常奇特/复杂的SQL。我已经使用@vars在SQL查询中应用'程序'逻辑。
- J Jorgenson -
答案 1 :(得分: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的帮助!
答案 2 :(得分:0)
在SQL分析器中尝试。如果你想要安全,不必信任数据库以单向工作(而不是在新版本中改变那种行为),只需进行两次查询并以编程方式执行IF。
答案 3 :(得分: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的警告相同。