在SQL中查找匹配的项目列表

时间:2014-04-17 19:45:13

标签: sql sql-server relational-algebra

我在另一个表中有一个表和一个相关的属性列表。它看起来像这样:

单位

ID | State | ...
----------------
 1 |    10 | ...
 2 |    15 | ...
 3 |    10 | ...

(状态在这里没有意义,我只是添加它以显示此表包含其他列)

形状

ID | Unit_ID (FK) | Shape
-------------------------
 1 |            1 |    40
 2 |            1 |    40
 3 |            1 |    45
 4 |            3 |    10

基本上Unit中的每一行都可以有各种相关的形状。形状的顺序并不重要,但形状可以多次关联。

在我的示例中,Units具有以下形状:

  • Unit 140, 40, 45
  • Unit 2:无
  • Unit 310

到目前为止一切顺利。这在获取/更新给定Unit - ID的完整形状集时工作正常。

但我要求选择具有相关Units列表的所有Shapes。例如,我想查找具有Units Shapes的所有40, 40, 45(应返回Unit_ID 1)。

我已经找到了一些使用关系划分的类似问题和文章,但我不确定这是否有效,因为大多数解决方案都无法处理多次出现的值。我希望得到完全匹配,如果我搜索40, 45我希望查询在我的示例中没有返回任何结果,因为没有Unit正好匹配Shapes(我会还需要一个查询来处理这种情况 - 选择包含子集的Units Shapes - 但是一旦我知道如何搜索完全匹配,这可能很容易。

我正在使用SQL Server 2012.

1 个答案:

答案 0 :(得分:2)

以下方法首先将列表放入表格(井,CTE)中,每个形状和计数次数。然后,它会进行各种检查。

首先,shapes中的每个形状都显示正确的次数。这就是内部聚合的来源。

然后,它会计算匹配的形状数,并验证这是tofind中不同形状的总数:

with tofind as (
      select 40 as shape, 2 as cnt union all
      select 45 as shape, 1 as cnt
     )
select s.unit_id
from (select s.unit_id, tofind.cnt as tf_cnt, count(s.id) as s_cnt
      from shapes s join
           tofind
           on s.shape = tofind.shape
      group by s.unit_id, tofind.shape, tofind.cnt
     ) s
group by s.unit_id
having sum(case when s_cnt = tf_cnt then 1 else 0 end) = (select count(*) from tofind);

编辑:

Here是一个SQL Fiddle,证明它有效。但是,上面的代码并不寻找完全匹配,因为其他形状可能在记录中。以下修改仅适用于完全匹配:

with tofind as (
      select 40 as shape, 2 as cnt union all
      select 45 as shape, 1 as cnt
     )
select s.unit_id
from (select s.unit_id, tofind.cnt as tf_cnt, count(s.id) as s_cnt
      from shapes s left outer join
           tofind
           on s.shape = tofind.shape
      group by s.unit_id, tofind.shape, tofind.cnt
     ) s
group by s.unit_id
having sum(case when s_cnt = tf_cnt then 1 else 0 end) = (select count(*) from tofind) and
       count(*) = sum(case when s_cnt = tf_cnt then 1 else 0 end);

区别在于left outer joinhaving子句中的附加条件。

相关问题