SQL 查询 - 确保 () 中的每个值都存在一行
Posted
技术标签:
【中文标题】SQL 查询 - 确保 () 中的每个值都存在一行【英文标题】:SQL Query - Ensure a row exists for each value in () 【发布时间】:2010-10-12 19:38:44 【问题描述】:目前正在努力寻找一种方法来验证 2 个表(表 A 的有效行数很多)
我有两张桌子
表 A
ID
A
B
C
表匹配
ID Number
A 1
A 2
A 9
B 1
B 9
C 2
我正在尝试编写一个 SQL Server 查询,该查询基本上检查以确保表 A 中的每个值都存在一组变量值(1、2、9)的行
上面的例子是不正确的,因为 t 应该为 A 中的每个记录在 Table 中与每个值 (1,2,9) 匹配的相应记录。最终目标是:
表匹配
ID Number
A 1
A 2
A 9
B 1
B 2
B 9
C 1
C 2
C 9
我知道它令人困惑,但通常对于(某些集合)中的每个 X 都应该在 Table 中匹配相应的记录。我显然已经简化了一些事情。
如果你们都需要澄清,请告诉我。
【问题讨论】:
总是存在三个值吗?值是否始终为 1、2 和 9? 不,实际上有 17 个值......而且它们不是连续的。 (1,3,4,5 7 等) 【参考方案1】:用途:
SELECT a.id
FROM TABLE_A a
JOIN TABLE_B b ON b.id = a.id
WHERE b.number IN (1, 2, 9)
GROUP BY a.id
HAVING COUNT(DISTINCT b.number) = 3
COUNT 中的 DISTINCT 确保重复项(即:A 在 TABLE_B 中有两条记录,值为“2”)不会被错误地视为正确记录。如果number
列具有唯一或主键约束,则可以省略它。
HAVING COUNT(...)
必须等于IN
子句中提供的值的数量。
【讨论】:
我认为这会起作用,愚蠢的简单(令人沮丧)。现在测试。谢谢。 @Nix:我想我可以让它更复杂? :)【参考方案2】:创建所需值的临时表。如果值 1、2 和 9 在您可以查询的某个表中,则可以动态执行此操作。
那么,SELECT FROM tempTable WHERE NOT IN (SELECT * FROM TableMatched)
【讨论】:
我需要确保每一行 IN 中的所有值都存在于匹配表中。这不会告诉我我是否有不存在的价值观吗? 如果缺少记录,您希望发生什么?如果所有需要的记录都存在于 TableMatched 中,我的 SELECT 将不会返回任何记录。那就是通过测试,对吧?如果这里有返回记录,则测试失败。你想让这个 SQL 插入缺失的记录吗?【参考方案3】:我曾经遇到过这种情况。我的解决方案如下。
除了 TableA 和 TableMatched 之外,还有一个表为 TableA 中的每一行定义了 TableMatched 中应该存在的行。我们称之为 TableMatchedDomain。
然后应用程序通过控制返回行的视图访问 TableMatched,如下所示:
create view TableMatchedView
select a.ID,
d.Number,
m.OtherValues
from TableA a
join TableMatchedDomain d
left join TableMatched m on m.ID = a.ID and m.Number = d.Number
这样,返回的行总是正确的。如果 TableMatched 中缺少行,则仍然返回 Numbers 但 OtherValues 为 null。如果 TableMatched 中有额外的值,则根本不会返回它们,就好像它们不存在一样。通过更改 TableMatchedDomain 中的行,可以非常轻松地控制此行为。如果删除了一个值 TableMatchedDomain,那么它将从视图中消失。如果以后再添加回来,那么对应的 OtherValues 就会像以前一样再次出现。
我这样设计的原因是我觉得在 TableMatched 中的行配置上建立一个不变量太脆弱了,更糟糕的是,它引入了冗余。所以我从行组中删除了限制(在 TableMatched 中),而是让另一个表(TableMatchedDomain)的全部内容定义了数据的正确形式。
【讨论】:
以上是关于SQL 查询 - 确保 () 中的每个值都存在一行的主要内容,如果未能解决你的问题,请参考以下文章
SQL JOINSQL INNER JOIN 关键字SQL LEFT JOIN 关键字SQL RIGHT JOIN 关键字SQL FULL JOIN 关键字