【问题标题】:Active record where.not returns empty array活动记录 where.not 返回空数组
【发布时间】:2017-11-02 17:29:11
【问题描述】:

以下命令

Fight.last.fight_logs.where(item_id: nil)

生成sql:

Fight Load (0.3ms)  SELECT  "fights".* FROM "fights" ORDER BY "fights"."id" DESC LIMIT $1  [["LIMIT", 1]]
FightLog Load (0.2ms)  SELECT  "fight_logs".* FROM "fight_logs" WHERE "fight_logs"."fight_id" = $1 AND "fight_logs"."item_id" IS NULL LIMIT $2  [["fight_id", 27], ["LIMIT", 11]]

然后返回:

#<ActiveRecord::AssociationRelation [#<FightLog id: 30, fight_id: 27, attack: 0, block: 0, item_id: nil, user_id: 1, damage: 11.0, created_at: "2017-11-02 16:20:55", updated_at: "2017-11-02 16:20:57">, #<FightLog id: 31, fight_id: 27, attack: 0, block: 0, item_id: nil, user_id: 20, damage: 3.0, created_at: "2017-11-02 16:20:57", updated_at: "2017-11-02 16:20:57">, #<FightLog id: 33, fight_id: 27, attack: 0, block: 0, item_id: nil, user_id: 1, damage: 1.0, created_at: "2017-11-02 16:21:40", updated_at: "2017-11-02 16:21:40">, #<FightLog id: 32, fight_id: 27, attack: 0, block: 0, item_id: nil, user_id: 20, damage: 7.0, created_at: "2017-11-02 16:21:33", updated_at: "2017-11-02 16:21:40">, #<FightLog id: 34, fight_id: 27, attack: 0, block: 0, item_id: nil, user_id: 1, damage: 12.0, created_at: "2017-11-02 16:21:47", updated_at: "2017-11-02 16:21:48">, #<FightLog id: 35, fight_id: 27, attack: 0, block: 0, item_id: nil, user_id: 20, damage: 14.0, created_at: "2017-11-02 16:21:48", updated_at: "2017-11-02 16:21:48">]>

但是

Fight.last.fight_logs.where.not(item_id: 1)

生成sql:

Fight Load (1.0ms)  SELECT  "fights".* FROM "fights" ORDER BY "fights"."id" DESC LIMIT $1  [["LIMIT", 1]]
FightLog Load (0.8ms)  SELECT  "fight_logs".* FROM "fight_logs" WHERE "fight_logs"."fight_id" = $1 AND ("fight_logs"."item_id" != $2) LIMIT $3  [["fight_id", 27], ["item_id", 1], ["LIMIT", 11]]

然后返回:

#<ActiveRecord::AssociationRelation []>

这怎么可能?我做错了什么?

【问题讨论】:

    标签: sql ruby-on-rails activerecord


    【解决方案1】:

    您应该在查询中指定 NULL 值,因为您的数据库中有它:

    Fight.last.fight_logs.where('item_id != ? OR item_id IS NULL', 1)
    

    这正是 SQL 的工作原理:

    select 1 != NULL;
    +-----------+
    | 1 != NULL |
    +-----------+
    |      NULL |
    +-----------+
    

    您可以查看this answer 来澄清问题。 另外,我建议避免在数据库中使用默认的 NULL 值,answer 很好。您可以简单地使用default: 0, null: false 您的案例。

    【讨论】:

    • @MrYoshiji You have passed Hash object to #or. Pass an ActiveRecord::Relation object instead
    • @MrYoshiji 使用 Rails 5
    • @Src 使用.or(Flight.last.flight_logs.where(item_id: nil))(您可以将此范围存储在变量中)
    • @MrYoshiji,我更喜欢我目前的答案(IMO 它比这个长范围更干净)。
    • 我同意,但我认为最好展示不同的选项,然后争论哪个更好。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-07
    • 2014-04-05
    • 2017-02-05
    • 1970-01-01
    • 1970-01-01
    • 2021-10-19
    相关资源
    最近更新 更多