高效验证一个表是否是另一个表的子集的方法

3

我有两个表A和B,结构完全相同。我需要验证A是B的一个子集。因为结构包含100多个字段,我不想在where谓词中逐个列出它们。

我想知道是否有更简单的方法来做到这一点


可能是[sql:检查表A中的条目是否存在于表B中]的重复问题(https://dev59.com/zWUo5IYBdhLWcg3wkQJq) - Obsidian Age
我认为你可以将A表和B表进行UNION,然后进行去重。如果结果的COUNT与A表中的数量相同,那么A表中就不可能有任何不在B表中的行。 - robertoplancarte
你可以考虑使用Information schemas编写带有动态SQL的存储过程。 - Derviş Kayımbaşıoğlu
@robertoplancarte,如果A表没有重复记录,这个方法可以工作。你需要对两边进行去重。 - Derviş Kayımbaşıoğlu
2个回答

8

假设:

(1) AB具有相同的表结构。这意味着列的顺序和数据类型必须匹配。

(2)A中没有重复行。

问题描述

为了证明A是B的子集,您需要显示A\B = 空集

解决方案

这意味着如果您删除每个在B中与A匹配的行,且输出为空(0行),则意味着A是B的子集

另一方面,如果输出中有> 0行,则意味着A具有B中没有的行,因此A不是B的子集

SELECT * FROM A
EXCEPT
SELECT * FROM B

A 为空(包含 0 行)时,它将被视为 B 的子集,因为上述查询的结果将为 0 行。

1
这基于所有行都是普遍唯一的想法。如果A有两行完全重复,那么B只需要一个这样的行就会导致EXCEPT返回零行。 - MatBailie
2
如果我们谈论集合理论,那么不允许有重复项,但确实,如果表允许数据重复,这可能是问题所在。我会将其作为假设包含在内。对于这种情况,我们需要更复杂的代码。好观点! - Kamil Gosciminski
如果我们想考虑重复项,那么这里的主要问题是我们基于集合运算符。我认为仅使用集合运算符而不考虑列无法解决(具有重复数据)。我看不出如何确定哪些记录是重复的。可能存在以下情况:A中有一个重复项,但B中的不同行也有一个重复项。请纠正我如果我错了。 - Kamil Gosciminski
解决方法是添加一个派生列,使所有行都唯一。例如,如果表有三个列,您可以向两个表中都添加 ROW_NUMBER() OVER (PARTITION BY a, b, c ORDER BY NULL) AS differentiator(或类似语句),然后应用 EXCEPT 方法。 - MatBailie
考虑过这个问题,但是这违反了在代码中不提及列名的规定,因为我们可能需要 OP 提到的所有 100 列。不过对于一个查询来说并不难,我肯定会选择这种方式。 - Kamil Gosciminski

-1

@robertoplancarte的方法稍加调整

with tB_cnt as 
(
    SELECT COUNT(*) cnt FROM
    (
        SELECT DISTINCT * FROM dbo.T_B 
    ) T_B
), TAB_cnt as 
(
    SELECT count(*) cnt FROM 
    (
        SELECT * FROM dto.T_B
        UNION
        SELECT * FROM dto.T_A          
    ) T_AB
)
SELECT 
  CASE WHEN TB_CNT.CNT = TAB_CNT.CNT THEN 
    'Table A is subset of B' 
  else 
    'Table A is not subset of B' 
  END as Result
FROM TAB_CNT, TB_CNT

1
UNION 已经删除了重复项,DISTINCT 是多余的。 - MatBailie
我认为你可能是想说交集(INTERSECT)而不是并集(UNION)。 - MatBailie
如果T_A有500行,而T_B具有与T_A相同的300行,则union操作将返回T_A的500行,因此我们得出结论T_B是T_A的子集,因为结果计数保持不变。是吗? - Derviş Kayımbaşıoğlu
我明白你的意思了。我误解了问题。修正了方法。 - Derviş Kayımbaşıoğlu
只是为了记录,我没有给这个答案点踩。 - Kamil Gosciminski
显示剩余7条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接