不应该`where.not(field:“something”)`include`where(field:nil)`?

时间:2014-10-14 21:51:23

标签: ruby-on-rails-4 arel

也许我会发疯,或者只是需要休息一下,但在我的rails控制台Order.where(state: nil).count中会返回1010,但Order.where.not(state: "pending").count会返回0 ...如果是order的状态为nil,然后它不是“pending”,所以我希望not(state: "pending")返回的集合包含集合where(state: nil)

这不是这样的吗?如果没有,是否会以不同的方式工作?

编辑:更多信息!当我去另一个数据库,其中一些记录的状态不是nil,我运行Order.where.not(state: "pending").count我得到了一堆订单,其中没有一个是“待定”,但也没有一个是零。似乎where.not隐含地在查询中添加了and not nil

编辑:在绝望中,我已经转向更黑暗的精神。

# look into another shop, that has records
o = Order.where(shop_id: 2)

# summon dread spirits
t = Order.arel_table[:state]

o.where(t.eq(nil).or(t.eq("pending").not)).count

=> 1569

o.where(t.eq(nil)).count

=> 1471

所以在这种情况下,我得到的98条记录的状态既不是nil也不是“pending”,我得到状态为nil的所有记录。我真的很想知道为什么我不能只说where.not("pending")并且具有相同的效果。如果有可能我可以调用的选项?比如,where.not("pending", include_nil: true)

编辑:根据@Filip Bartuzi的评论要求

Order.where.not(state: "pending").to_sql

=> "SELECT \"orders\".* FROM \"orders\"  WHERE \"orders\".\"shop_id\" = 2 AND (\"orders\".\"state\" != 'pending')"

Orders.where(state: nil).to_sql

=> "SELECT \"orders\".* FROM \"orders\"  WHERE \"orders\".\"shop_id\" = 2 AND \"orders\".\"state\" IS NULL"

2 个答案:

答案 0 :(得分:5)

Order.where.not(state: "pending").to_sql生成:

=> "SELECT \"orders\".* FROM \"orders\" WHERE \"orders\".\"shop_id\" = 2 AND (\"orders\".\"state\" != 'pending')"

它将返回VALUES中未处于“待定”状态的所有记录。当您将pending设置为nil时(如Order.first.update! state: nil,它会在数据库中指定NULL

NULL在SQL中不会被解释为值,因此它不会包含在SELECT响应中

答案是:where.not(field: “something”)不包含where(field: nil)

您可以在此处查看其工作原理:

http://www.w3schools.com/sql/trysql.asp?filename=trysql_select_all

转到类别表并首先执行

UPDATE Categories
SET CategoryName = NULL
WHERE CategoryName = 'Beverages'

现在我们有了Count 8的类别,其中一个在NULL列上有CategoryName

现在执行:

SELECT CategoryName FROM Categories
WHERE CategoryName != 'Condiments'

如您所见,返回了6条记录(因此它跳过了一条NULL

答案 1 :(得分:2)

SQL实现遵循3值逻辑,其中NULL不是值,但标记缺少值。 3值逻辑为逻辑运算定义了以下真值表:( null在这里是未知的)

p       |q      |p OR q |p AND q|p = q
True    |True   |True   |True   |True
True    |False  |True   |False  |False
True    |Unknow |True   |Unknown|Unknown
False   |True   |True   |False  |False
False   |False  |False  |False  |True
False   |Unknown|Unknown|False  |Unknown
Unknown |True   |True   |Unknown|Unknown
Unknown |False  |Unknown|False  |Unknown
Unknown |Unknown|Unknown|Unknown|Unknown

由于where测试数据集中每个条目的相等性(row.state == 'pending'),如果row.state为NULL,则通过上面的真值表得出结果为' Unknown& #39 ;. '未知'不是真的,所以行不包含在结果集中。

Wikipedia的更多信息。