嗨大家我有一个表格关系,就像这样(遗产)
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的子集。
答案 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_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
请注意,将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))