我有一个名为 A
的模型,其中包含列 col
和 col2
。 col1
有一个唯一索引。 (我正在使用 Postgres 数据库。)
class A < ActiveRecord::Base
# id, col1, col2
end
数据:
id col1 col2
== ==== ====
1 2 3
2 3 4
让我们尝试在 col2
或 col1
中找到与给定值匹配的第一行。
a = A.first(:conditions=> ["col2 = :id OR col1 = :id", {:id => 3}])
# select * from A where (col2 = 3 OR col1 = 3) LIMIT 1
上面的 SQL 返回第 2 行而不是第 1 行。我怀疑查询优化器选择首先执行 col1 = 3
,因为 col1
具有唯一索引。
如何覆盖此行为?我如何指示 Postgres 优化器将现有顺序用于 OR 条件?
最佳答案
如果您没有指定明确的顺序,那么第一行就没有任何意义;特定时刻特定查询的结果集当然会有第一行,但不能保证使用相同数据再次运行相同查询会产生相同的第一行。关系数据库中的表没有排序,因此根本没有指定的现有顺序。你在做一个错误的假设;该实现可能会隐式地按磁盘上的 PK 对记录进行排序,但不能保证这一点,也不能保证下一个版本的行为相同;此外,不能保证数据库将按磁盘顺序返回行,除非您使用 ORDER BY 子句指定了特定顺序,否则数据库可以自由地以任何方式对行进行排序。
如果你想要一个订单,那么你应该包含一个 ORDER BY 子句;你可能想要更像这样的东西:
a = A.where("col2 = :id OR col1 = :id", {:id => 3}).order(:id).first
如果你想在 col1
之前查看 col2
那么你应该这样说:
a = A.where('col2 = :id', :id => 3).order(:id).first \
|| A.where('col1 = :id', :id => 3).order(:id).first
col2 = :id OR col1 = :id
和 col1 = :id OR col2 = :id
是等效的 bool 表达式,因此数据库可以自由检查 col2 = :id
在 col1 = :id
之前、之后或同时,它可以按照它喜欢的任何顺序自由访问行。
关于sql - 如何在 Postgres/Rails 中禁用 OR 条件优化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8555920/