【问题标题】:Why is arel adding unnecessary parentheses to 'a and b or c and d or ..' query为什么 arel 在 'a and b or c and d or ..' 查询中添加不必要的括号
【发布时间】:2014-05-12 15:21:34
【问题描述】:

这是一个例子(没有意义,但作为一个例子很好)

t = DimensionType.arel_table

q = t.where(
          t[:label].eq('a').and(t[:label].eq('b'))
      .or(t[:label].eq('c').and(t[:label].eq('d')))
      .or(t[:label].eq('e').and(t[:label].eq('f')))
      .or(t[:label].eq('g').and(t[:label].eq('e')))
  ).to_sql

 puts q

这是输出:

SELECT FROM "dimension_types"  WHERE ((("dimension_types"."label" = 'a' AND "dimension_types"."label" = 'b' OR "dimension_types"."label" = 'c' AND "dimension_types"."label" = 'd') OR "dimension_types"."label" = 'e' AND "dimension_types"."label" = 'f') OR "dimension_types"."label" = 'g' AND "dimension_types"."label" = 'e')

括号有什么作用?如果没有,如何避免拥有它们?他们将 where 部分置于一种可能会影响查询优化的层次结构中。

编辑: 目的是进行这样的查询(使用人为的元语言):

(a and b) or (b and c) or (d and e)

没有括号也一样,因为and 优先于or

a and b or b and c or d and e

如果我错了,请纠正我。

【问题讨论】:

  • 括号改变了布尔运算符的优先顺序,并将逻辑组合在一起。没有它们,含义完全不同(基于从左到右的阅读顺序和 AND/OR 的相对优先级)。简单来说,没有括号 AND 总是在 OR 之前评估。

标签: sql ruby-on-rails ruby ruby-on-rails-4 arel


【解决方案1】:

括号改变布尔运算符的优先顺序,并将逻辑组合在一起。没有它们,含义完全不同(基于从左到右的阅读顺序和 AND/OR 的相对优先级)。

简单来说,没有括号的 AND 总是在 OR 之前计算。

这些不等价

 A and B or C
 A and (B or C)

第一个评估 A and B,然后用 C 评估 ors。第二个评估 ors B 和 C,然后用 A 评估 anding。

括号确保以特定顺序执行特定的逻辑分组。

更新:

在您的特定情况下,您希望所有 AND 在 OR 之前进行评估,但 LINQ 通过在幕后导航逻辑“树”将逻辑转换为 SQL,您无法控制该过程。它这样做是为了确保结果符合您的预期,这通常意味着额外的括号。

由于大部分处理时间用于从驱动器获取数据,而不是评估 SQL 中的括号,因此您不必担心。您可以假设任何优化都将在更广泛的层面上发挥作用,并且尽管有括号仍然有效(实际上它甚至可能更有效地工作):)

【讨论】:

  • 我不确定我是否理解您的回答。 'AND 在 OR 之前评估'是我的查询的预期行为,因此即使没有任何括号,查询也应该没问题。还是不行?
  • 在你的情况下是正确的。 LINQ 解析似乎将您的查询评估为一棵逻辑树,并以确保您想要的相同评估的顺序吐出逻辑。它可能并不完美,但你无法控制它。将添加他的答案。
  • 我想我的主要问题是生成的 sql 可读性较差,让我有点困惑。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-06-13
  • 2021-11-28
  • 2015-11-29
  • 2015-10-14
  • 1970-01-01
  • 1970-01-01
  • 2019-04-12
相关资源
最近更新 更多