与普通的SQL相比,我更喜欢activerecord,因此遇到了一些麻烦。
我有一个关系表,其中有一个名为sequence的属性,它是array类型的。数组为空或包含一系列数字。
我试图实现的是编写一个AR作用域,它允许我只返回序列数组大小等于num
的记录。我想它看起来像这样:
def self.of_order(num)
where("array_length(sequence, 1) = ?", num)
end
如果它在活动记录中可用,我可以想象它是:
def self.of_order(num)
where(sequence.size == num)
end
编辑:
以下是迁移的情况:
class CreateRelationships < ActiveRecord::Migration
def change
create_table :relationships do |t|
t.integer :root_id
t.integer :destination_id
t.boolean :first_order?
t.text :sequence, array: true, default: []
t.timestamps null: false
end
end
end
样本数据:
[
[ 0] #<Relationship:0x007f8d5a5c82c8> {
:id => 73,
:root_id => 51,
:target_id => 52,
:first_order? => true,
:sequence => [],
:created_at => Thu, 20 Oct 2016 19:05:22 UTC +00:00,
:updated_at => Thu, 20 Oct 2016 19:05:22 UTC +00:00,
:primitive_type => "spouse"
},
[ 1] #<Relationship:0x007f8d5a5c8188> {
:id => 74,
:root_id => 52,
:target_id => 51,
:first_order? => true,
:sequence => [22,43,90],
:created_at => Thu, 20 Oct 2016 19:05:22 UTC +00:00,
:updated_at => Thu, 20 Oct 2016 19:05:22 UTC +00:00,
:primitive_type => "spouse"
}
]
我希望
Relationship.all
返回两个记录,Relationship.of_order(0)
返回第一条记录,Relationship.of_order(3)
要返回第二条记录,并
Relationship.of_order(2)
返回无。 最佳答案
我认为问题的根源在于当数组为空时array_length
是null
:
=> select array_length(array[]::text[], 1);
array_length
--------------
(1 row)
=> select coalesce(array_length(array[]::text[], 1), 0);
coalesce
----------
0
(1 row)
这并没有明确的记录,所以如果你错过了就不要难过。
因此:
def self.of_order(num)
where("array_length(sequence, 1) = ?", num)
end
Relationship.of_order(6)
会工作得很好,但是Relationship.of_order(0)
最终会尝试在数据库中执行null = 0
操作,这永远不是真的,因此您找不到空数组。想到两个简单的解决方案:
您可以在您的范围内显式处理
of_order(0)
情况:def self.of_order(num)
if(num == 0)
where('array_length(sequence, 1) is null')
else
where('array_length(sequence, 1) = ?', num)
end
end
向查询中抛出一个
coalesce
调用,将空值转换为零,并让数据库担心:def self.of_order(num)
where('coalesce(array_length(sequence, 1), 0) = ?', num)
end
关于sql - 在ActiveRecord中的WHERE语句中使用array_length,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/40163966/