1

嗨,伙计们,我有一个像这样工作的表关系(旧版)

A有很多B,B有很多C;A 也有很多 C

现在我很难想出一个 SQL,它可以帮助我将所有 B(B 的 ID 使其简单化)映射到某个 A(按 Id)和任何具有 C 集合的 B 集合,该集合是 Cs 的子集那个A。

我没有专门为第二部分想出一个像样的 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'

所以我正在寻找 Bs,其 C_Values 是某些 A_C_Values 的子集。

4

3 回答 3

1

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

现在,如果我们使用外连接,我们将能够看到 in 中的哪些行与 inB_C_Table不匹配A_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

请注意,将inac.A_ID = @A_ID放入ON子句而不是 into很重要WHERE,因为在后一种情况下,我们将过滤掉 的不匹配行@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与 的子集中的任何行都不匹配A_C_Table,我们将看到和的不同值。TotalCountMatchCount

从逻辑上讲,这将我们引向最后一步:比较这些计数。(因为,很明显,如果我们可以获得值,我们也可以比较它们。)但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联合A_B_rel

SELECT B_ID
FROM A_B_rel
WHERE A_ID = @A_ID

UNION

SELECT bc.B_ID
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)
于 2012-07-03T07:53:53.310 回答
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))
于 2012-07-03T16:23:16.017 回答
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>作为输入参数)。

于 2012-07-03T04:21:48.283 回答