与普通的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_lengthnull

=> 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/

10-10 14:40