查找与另一个表

时间:2017-07-07 20:44:14

标签: sql sql-server relational-division exact-match

鉴于这些表格:

表:测试

专栏:

  • testID int PK
  • name nvarchar(128)UNIQUE NOT NULL

表:[测试输入]

  • inputsTableName nvarchar(128)UNIQUE PK
  • testID int PK FK

临时表:## TestSearchParams

列:

  • inputsTableName nvarchar(128)UNIQUE NOT NULL

我需要找到Test-Inputs中包含条目的测试,其中的inputTableNames恰好与## TestSearchParams中的所有条目匹配;生成的测试关系必须与## TestSearchParams中列出的完全相同。

基本上我只能找到给定关系的测试,不多也不少。我将名称与LIKE和通配符匹配,但这是一个旁注,我相信我可以在核心逻辑完全匹配后解决。

这是我目前的查询:

Select *
From   Tests As B
Where  B.testID In (
                       Select ti
                       From   (
                                  Select   (
                                               Select Count(inputsTableName)
                                               From   [Test-Inputs]
                                               Where  [Test-Inputs].testID = B.testID
                                           ) - Count(Distinct i1) As delta,
                                           ti
                                  From     (
                                               Select [Test-Inputs].inputsTableName As i1,
                                                      [Test-Inputs].testID As ti
                                               From   ##TableSearchParams
                                               Join   [Test-Inputs]
                                                   On [Test-Inputs].inputsTableName Like ##TableSearchParams.inputsTableName
                                                      And B.testID = [Test-Inputs].testID
                                           ) As A
                                  Group By ti
                              ) As D
                       Where  D.delta = 0
                   );

目前的问题是他似乎检索了与## TableSearchParams中任何条目匹配的测试。在此之前我已经尝试过其他几个问题,以获得不同程度的成功。我有查找匹配任何参数,所有参数和任何参数的测试的查询 - 我只是不能让这个查询工作。

以下是一些示例表值:

测试

  • 1,Test1
  • 2,Test2
  • 3,Test3

[试验输入]

  • 表1,1
  • 表2,2
  • 表1,3
  • 表2,3

TestSearchParams

  • 表1
  • 表2

给定的值应该只返回(3,Test3)

1 个答案:

答案 0 :(得分:0)

这里有一个可行的解决方案,它通过为测试中的每个记录获取完整的TestInput集合,左连接到搜索参数集,然后通过测试聚合结果并进行两次观察:

首先,如果测试中的记录包含不在搜索参数中的TestInput,则必须从结果集中排除该记录。我们可以通过查看是否存在上述左连接在搜索参数表中没有产生匹配的情况来检查这一点。

其次,如果来自测试的记录满足第一个条件,那么我们就知道它没有任何多余的TestInput记录,所以唯一的问题是它是否存在不属于它的搜索参数TestInputs。如果是这样,那么我们为该测试聚合的记录数将少于搜索参数的总数。

我在此假设您没有包含重复TestInput的测试记录,并且您同样不使用重复的搜索参数。如果这些假设无效,那么这就变得更加复杂。但如果他们是,那么这应该工作:

declare @Tests table (testID int, [name] nvarchar(128));
declare @TestInputs table (testID int, inputsTableName nvarchar(128));
declare @TestSearchParams table (inputsTableName nvarchar(128));

-- Sample data.
--
-- testID 1 has only a subset of the search parameters.
-- testID 2 matches the search parameters exactly.
-- testID 3 has a superset of the search parameters.
--
-- Therefore the result set should include testID 2 only.
insert @Tests values
    (1, 'Table A'), 
    (2, 'Table B'), 
    (3, 'Table C');
insert @TestInputs values
    (1, 'X'),
    (2, 'X'),
    (2, 'Y'),
    (3, 'X'),
    (3, 'Y'),
    (3, 'Z');
insert @TestSearchParams values 
    ('X'), 
    ('Y');

declare @ParamCount int;
select @ParamCount = count(1) from @TestSearchParams;

select
    Tests.testID,
    Tests.[name]
from
    @Tests Tests
    inner join @TestInputs Inputs on Tests.testID = Inputs.testID
    left join @TestSearchParams Search on Inputs.inputsTableName = Search.inputsTableName
group by
    Tests.testID,
    Tests.[name]
having
    -- If a group includes any record where Search.inputsTableName is null, it means that
    -- the record in Tests has a TestInput that is not among the search parameters.
    sum(case when Search.inputsTableName is null then 1 else 0 end) = 0 and

    -- If a group includes fewer records than there are search parameters, it means that
    -- there exists some parameter that was not found among the Tests record's TestInputs.
    count(1) = @ParamCount;