SQL查询构造:检查查询结果是否是另一个的子集

时间:2012-07-03 03:41:26

标签: sql sql-server-2008

嗨大家我有一个表格关系,就像这样(遗产)

A有很多B和B有很多C; A还有很多C

现在我无法想出一个SQL,这将帮助我将所有B(B的ID简化)映射到某个A(通过Id)和任何具有C的集合的B是子集那个A的Cs。

我没有为第二部分特别提出一个不错的sql,并且想知道我是否可以得到任何提示/建议我是如何做到的。

由于

编辑:

Table A

Id     |..
------------
 1     |..




Table B

Id     |..
--------------
2      |..

Table A_B_rel 

A_id  |    B_id
-----------------
1     |     2

C是一张奇怪的表格。 C(单列)的数据实际上只是在A和B的2 rel表中使用,所以就像这样

Table B_C_Table

B_Id| C_Value
-----------------
2   | 'Somevalue' 

Table A_C_Table

A_Id| C_Value
-------------
1   |    'SomeValue'

所以我正在寻找B的C_Values,它们是某些A_C_Values的子集。

3 个答案:

答案 0 :(得分:1)

也许这就是你要找的东西:

SELECT B_id
FROM A_B_rel
WHERE A_id = <A ID>

UNION

SELECT a.B_Id
FROM B_C_Table a
LEFT JOIN A_C_Table b ON a.C_Value = b.C_Value AND b.A_Id = <A ID>
GROUP BY a.B_Id
HAVING COUNT(CASE WHEN b.A_Id IS NULL THEN 1 END) = 0

第一个SELECT获取映射到特定B的所有A<A ID>作为A ID的输入参数),然后我们将其添加到该结果设置任何其他B整个 C_Value C_Value的子集特定A(同样,<A ID>是输入参数)。

答案 1 :(得分:1)

是的,问题的第二部分有点棘手。我们一方面有B_C_Table,另一方面有A_C_Table的子集,其中A_ID是特定的ID。

现在,如果我们使用外部联接,我们将能够看到B_C_TableA_C_Table中哪些行不匹配:

SELECT *
FROM B_C_Table bc
  LEFT JOIN A_C_Table ac ON bc.C_Value = ac.C_Value AND ac.A_ID = @A_ID

请注意,将ac.A_ID = @A_ID放入ON子句而不是放入WHERE非常重要,因为在后一种情况下,我们将过滤掉{{{}的非匹配行1}},这不是我们想要的。

下一步(实现最终查询)将按@A_ID对行进行分组并计算行数。现在,我们将计算总行数和匹配行的数量。

B

正如您所看到的,为了计算匹配数,我们只计算SELECT bc.B_ID, COUNT(*) AS TotalCount, COUNT(ac.A_ID) AS MatchCount FROM B_C_Table bc LEFT JOIN A_C_Table ac ON bc.C_Value = ac.C_Value AND ac.A_ID = @A_ID GROUP BY bc.B_ID 个值:如果不匹配,相应的列将为ac.A_ID,因此不会计算。如果NULL中的某些行确实与B_C_Table子集中的任何行都不匹配,我们会看到 {/ 1}}和A_C_Table

这在逻辑上引导我们走向最后一步:比较这些计数。 (显然,如果我们可以获得值,我们也可以比较它们。)但是当然不在TotalCount子句中,因为MatchCount中不允许使用聚合函数。它是WHERE子句,用于比较分组行的值,包括聚合值。所以......

WHERE

当然,并不真正需要计数值,当您放弃它们时,您可以使用从HAVING选择SELECT bc.B_ID, COUNT(*) AS TotalCount, COUNT(ac.A_ID) AS MatchCount FROM B_C_Table bc LEFT JOIN A_C_Table ac ON bc.C_Value = ac.C_Value AND ac.A_ID = @A_ID GROUP BY bc.B_ID HAVING COUNT(*) = COUNT(ac.A_ID) 的查询来联合上述查询:

B_ID

答案 2 :(得分:1)

听起来你需要考虑双重否定,即不应该存在任何没有匹配A_C的B_C(而且我猜应该至少有一个B_C)。

所以,试试像

这样的东西
select B.B_id
from Table_B B 
where exists (select 1 from B_C_Table BC
                  where BC.B_id = B.B_id)
  and not exists (select 1 from B_C_Table BC
                  where BC.B_id = B.B_id
                    and not exists(select 1 from B_C_Table AC
                                   join A_B_Rel ABR on AC.A_id = ABR.A_id
                                   where ABR.B_id = B.B_id
                                     and BC.C_Value = AC.C_Value))