如何有效地搜索具有一对多关系条件的记录

时间:2014-07-07 15:52:16

标签: sql one-to-many

说我有以下架构:

create table foo (
    foo_id      int not null,
    name        text not null,
    primary key (foo_id)
);

create table bar (
    bar_id      int not null,
    foo_id      int not null,
    index       int not null,
    value       text not null,
    primary key (bar_id),
    foreign key (foo_id) references foo (foo_id)
);

foobar之间的一对多关系; foobar的有序容器。

如何有效搜索foo包含某组bar s的记录?也就是说,如果我有一个bar.value的列表,那么foo对于每个bar都有一个关联的bar

请注意,我需要存储有关exists s顺序的信息,但希望在搜索时忽略排序。

我能想到的唯一方法是:

  • 使用bar子查询以编程方式为我感兴趣的每个值编写查询
  • 为我感兴趣的每个值以编程方式select f.* from foo f where exists (select 1 from bar b where b.foo_id = f.foo_id and value = 'value 1') and exists (select 1 from bar b where b.foo_id = f.foo_id and value = 'value 2') and ... exists (select 1 from bar b where b.foo_id = f.foo_id and value = 'value n') 编写内部联接的查询

例如:

select
    f.*
from
    foo f,
    bar b1,
    bar b2,
    ...
    bar bn
where
    b1.foo_id = f.foo_id and b1.value = 'value 1' and
    b2.foo_id = f.foo_id and b2.value = 'value 2' and
    ...
    bn.foo_id = f.foo_id and bn.value = 'value n'

根据您需要匹配的值动态构建。

可替换地:

{{1}}

有没有更好的方法在SQL中实现这一点?

我可以使用其他架构来简化这项工作吗?

2 个答案:

答案 0 :(得分:1)

我认为存在的技术是最好的。但如果你想以不同的方式做到这一点,也许这就是:

with x as (
select f.id
   from foo f
   join bar b
     on b.foo_id = f.id
  where b.value in ('value 1', 'value 2', ..., 'value n')
  group by f.id
  having count(distinct b.value)) = n
)
select f.*
   from foo f
   join x.id = f.id

如果我的语法错误,你将不得不原谅我。我没有建立一个数据库来测试我的答案。

我知道有些人不喜欢使用CTE,所以这里有另一种选择:

 select f.*
   from (
    select f.id
       from foo f
       join bar b
         on b.foo_id = f.id
      where b.value in ('value 1', 'value 2', ..., 'value n')
      group by f.id
      having count(distinct b.value)) = n
    ) x
   join foo f on f.id = x.id

答案 1 :(得分:0)

除非我在这里遗漏了一些内容,否则这两个表格之间看起来就像一个简单的Join

  

如何有效地搜索包含特定条形图的foo记录?也就是说,如果我有一个bar.values列表,那些foos每个都有一个关联的栏?

您可以使用以下内容找到与foo值相关联的bar

Select      Distinct f.foo_id, f.name
From        bar b
Inner Join  foo f On f.foo_id = b.foo_id
Where       b.value In ('your', 'search', 'values')