我的模型Foo
包含String
bar
和String
name
。某些记录“bar
包含其中name
个其他记录。这是故意的。
我想找到“根Foo”记录 - 即name
未出现在任何其他bar
记录的Foo
记录中的记录。
示例:
Foo
id: 1
name: 'foo1'
bar: 'something something'
id: 2
name: 'foo2'
bar: 'foo1 something'
id: 3
name: 'foo3'
bar: 'foo1, foo4'
我的方法root_foos
将返回foo2
和foo3
,因为它们的名称不会出现在任何bar
字符串中。
编辑:我不想在这里使用关系或外键 - 只是这种方法。
答案 0 :(得分:2)
SELECT f.*
FROM foo f
WHERE NOT EXISTS (
SELECT 1
FROM foo f2
WHERE f.name <@ string_to_array(f2.bar, ', ')
);
将', '
替换为您实际使用的分隔符
使用索引,这将更快。您可以构建一个功能性GIN索引来处理当前不幸的设计:
CREATE INDEX foo_bar_arr_gin_idx ON foo USING GIN (string_to_array(bar, ', '));
bar
应该实现为数组而不是字符串。然后你可以简化查询和索引:
Table indexes for Text[] array columns
Why isn't my PostgreSQL array index getting used (Rails 4)?
如链接答案中所述,如果正确实现n:m关系,数据库模式将更清晰(查询和索引更简单,更快)。性能取决于许多变量。
CREATE TABLE foo
foo_id serial PRIMARY KEY
, foo text
);
CREATE TABLE foo_foo
foo_id1 int REFERENCES foo
, foo_id2 int REFERENCES foo
, PRIMARY KEY (foo_id1, foo_id2) -- provides necessary index automatically
);
然后您的数据将如下所示:
foo
foo_id: 1
foo: 'foo1'
foo_id: 2
foo: 'foo2'
foo_id: 3
foo: 'foo3'
foo_foo
foo_id1: 1
foo_id2: some_id
foo_id1: 1
foo_id2: some_other_id
foo_id1: 2
foo_id2: 1
foo_id1: 2
foo_id2: some_id
foo_id1: 3
foo_id2: 1
foo_id1: 3
foo_id2: 4
查询:
SELECT f.*
FROM foo f
WHERE NOT EXISTS (
SELECT 1
FROM foo_foo f2
WHERE f2.foo_id2 = f.foo_id
);
答案 1 :(得分:-1)
对于任意数量的记录,这将是非常缓慢的,如果这是您需要的任何频率的查询,我强烈建议重构您的架构,但是:
objs = Model.all.to_a
objs.select { |obj| !objs.any? { |inner_obj| inner_obj[:bar].index(obj[:name]) } }