我有这样的查询:
select a.id from a join b on ( a.id = b.my_a ) join ....
where
( /* complex and expensive conditional */ )
AND
(( /* conditional #1 */ )
OR ( /* conditional #2 */ )
OR ( /* conditional #3 */))
我想让查询返回类似的内容:
select a.id, conditional_1_eval_value, conditional_2_eval_value, conditional_3_eval_value from a join b on ( a.id = b.my_a ) join ....
where
( /* complex and expensive conditional */ )
AND
(( /* conditional #1 */ )
OR ( /* conditional #2 */ )
OR ( /* conditional #3 */))
其中conditional_1_eval_value
,conditional_2_eval_value
和conditional_3_eval_value
设置为TRUE,FALSE,NULL。 NULL表示未评估条件。
所以结果集可能是:
1, FALSE, NULL, TRUE ( condition_1, condition_3 were evaluate, condition_2 was not)
2, NULL, TRUE, TRUE ( condition_2, condition_3 were evaluate, condition_1 was not)
3, TRUE, FALSE, FALSE (all were evaluated)
condition_1
,condition_2
,condition_3
本身很复杂,涉及相关子查询和分组。
编辑:
我们需要记录导致返回行的条件。我们不需要知道返回行的所有原因。因此,在结果示例的第二行中,知道conditional_2
和conditional_3
都是真的就足够了。不知道conditional_1
值是什么并不重要。
足以知道至少有一个条件满足,条件是什么条件。
显然,我可以使用 UNION 这样做:
select a.id, TRUE, NULL, NULL from a join b on ( a.id = b.my_a ) join ....
where
( /* complex and expensive conditional */ )
AND
( /* conditional #1 */ )
UNION
select a.id, NULL, TRUE, NULL from a join b on ( a.id = b.my_a ) join ....
where
( /* complex and expensive conditional */ )
AND
( /* conditional #2 */ )
UNION
select a.id, NULL, NULL, TRUE from a join b on ( a.id = b.my_a ) join ....
where
( /* complex and expensive conditional */ )
AND
( /* conditional #3 */)
但这意味着:
在选择中使用 CASE复制每个条件1到3可避免共同条件被评估3次。然而,条件1-3的复杂性使得它可能是不可能的。
在FROM 子句中使用 select会很尴尬,可能无法实现,因为FROM SELECT不能是相关查询。我不确定我是否可以构建一个有用的非相关查询。
存储过程可行。但是,这将是第一个这样的存储过程,并且会显着增加我们的部署复杂性。
在java代码中执行conditional_1
,conditional_2
,conditional_3
评估。这就是我们目前正在做的事情,它运行的是sloooooooow。当数据库被设计为过滤结果集时传输的大量数据 - 不应该在java中执行此操作!
任何?
我还应该补充一点,我欢迎那些说这个问题无法解决的答案。知道问题无法解决将节省我尝试用严格的SQL解决它的时间。
如果我必须选择,我会倾向于学习mysql存储过程的样子。
所以,如果你想自愿提供mysql存储过程看起来会很棒的东西。
答案 0 :(得分:2)
要实现您的目标,为什么不在复杂条件下使用存储函数?
这将导致选择语句,如:
select func1(arg1, arg2, ...), func2(arg1, arg2, ...), rest_of_select_columns
from table1, table2
where (complex1 logic)
OR func1(arg1, arg2, ....) = 1 /* return to give true */
OR func2(arg1, arg2, ....) = 1
注意:
答案 1 :(得分:1)
Franky,我不知道如何在MySQL(或实际上在任何SQL)中表达问题。但是,几年前我还面临着同样复杂,庞大的数据集评估问题 1 。
根据所收集的经验,我可以就如何加快评估提出一些想法:
1 实际上,约束是在~1M记录集上进行快速按需计算。
答案 2 :(得分:1)
你是正确的,将所有数据拉回到java并执行你的条件将是一只狗。
但是,你真正的选择是联合3种不同的查询。由于关系引擎如何工作,所以无法取出记录中的“命中”。
答案 3 :(得分:0)
您是否可以选择与结果相关的所有数据,然后在客户端代码中执行结果集中的条件逻辑?
答案 4 :(得分:0)
如果您希望减少复杂表达式的重新输入,请将表达式放在子查询派生表中:
SELECT t.*
FROM (
SELECT a.*, b.*, ...
/* conditional #1 */ AS c1,
/* conditional #2 */ AS c2,
/* conditional #3 */ AS c3
FROM a JOIN b ON (a.id = b.my_a)
...) AS t
WHERE /* ...other conditions... */
AND ((c1) OR (c2) OR (c3));
这也是一个不同问题的解决方案,“如何在WHERE条件中使用列别名?”