我在 Rails3 应用程序中遇到了意外的 postgres 查询问题。
我想我会通过 stackoverflow 运行它,看看互联网的大脑怎么说:)
这个结果是预期的行为(为什么?!)还是一个错误?
鉴于我的 Postgres 9.1.4 数据库中有一个表 Orders:
id state
===== ======
1 <-- nil (default value)
2 'success'
3 'failure'
当我运行查询时:
Order.where('orders.state != ?', 'success').map { |order| order.id }
Order Load (3.8ms) SELECT "orders".* FROM "orders" WHERE (orders.state != 'success')
=> [3]
我期待结果 [1, 3]。显然有 2 行满足 (!= 'success')。
为什么 nil != 'success' 在这里不是真的? != 是否只忽略 NULL 值?应该吗?
注意:我使用以下查询生成了所需的结果:
Order.where('orders.state IS NULL OR orders.state != ?', 'success').map { |order| order.id }
Order Load (2.3ms) SELECT "orders".* FROM "orders" WHERE (orders.state IS NULL OR orders.state != 'success')
=> [1, 3]
如有任何意见,我们将不胜感激。
最佳答案
有一个IS DISTINCT FROM PostgreSQL 中的比较运算符:
Ordinary comparison operators yield null (signifying "unknown"), not true or false, when either input is null. For example,
7 = NULL
yields null, as does7 <> NULL
. When this behavior is not suitable, use theIS [ NOT ] DISTINCT FROM
constructs:expression IS DISTINCT FROM expression expression IS NOT DISTINCT FROM expression
For non-null inputs,
IS DISTINCT FROM
is the same as the<>
operator. However, if both inputs are null it returns false, and if only one input is null it returns true. Similarly,IS NOT DISTINCT FROM
is identical to=
for non-null inputs, but it returns true when both inputs are null, and false when only one input is null. Thus, these constructs effectively act as though null were a normal data value, rather than "unknown".
例如,给定您的示例数据:
=> select * from orders where state is distinct from 'success';
id | state
----+---------
1 |
3 | failure
(2 rows)
所以你可以这样说:
Order.where('orders.state is distinct from ?', 'success').pluck(:id)
请注意,我还切换到 pluck
而不是你的 map(&:id)
,这会将此 SQL 发送到数据库:
select id from orders where orders.state is distinct from 'success'
而不是 select orders.* ...
使用客户端过滤器提取 id
关于sql - NULL 的结果!= SQL 查询中的值(postgres 和 rails3),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16486409/