SQL通过公共列中的精确组合连接两个表

时间:2017-08-07 12:49:57

标签: sql

我正在尝试匹配两个有两列的表;一个带有id号,另一个带有型号。

在第一个表中,id号可以有不同的类型号,例如id 1可以在第二个表中分配类型1,2,3,4 id 1可以分配类型1,2,4 ...我想只有在类型完全相同的情况下才能通过id加入表...

由于

1 个答案:

答案 0 :(得分:0)

根据您的编辑,您需要基于两个表中id和type的组合的INNER JOIN:

SELECT
   Table1.id
   , Table1.type
   , Table1.ColumnsYouNeed
   , Table2.ColumnsYouNeed
FROM
    Table1
    INNER JOIN Table2 ON Table1.id = Table2.id 
        AND Table1.type = Table2.type

这将确保您只能看到ID和类型匹配的两个表中的那些行。

实施例: 如果Table1包含id = 12345并且输入=' foo'并且Table2的id = 12345并且输入=' foo',您将看到数据(基于您添加到的相应列) Table1和Table2中的SELECT语句)。

如果Table1包含id = 12345并且键入=' foo',但Table2的id = 12345且只有type =' bar',则不会看到任何行。

如果您想要查看表1中的所有值,无论它们是否与表2中的匹配,请将INNER JOIN更改为LEFT JOIN。你想要全部展示吗? 表2中的值,无论表1中是否存在,您都可以将INNER JOIN更改为RIGHT JOIN

*根据您的评论更新*

我想我会展示JOINs如何运作的其他一些例子。

让我们首先设置一些包含样本数据的样本表:

CREATE TABLE #table1 (id tinyint, myType tinyint, columnA varchar(5));

INSERT INTO #table1 
VALUES (1, 1, 'aaaa'), (1, 2, 'aaab'), (1, 4, 'aaaac'), (2, 1, 'bbbbb'), (2,2, 'bbbbc'), (3, 1, 'dddd');

CREATE TABLE #table2 (id tinyint, myType tinyint, columnB varchar(25));

INSERT INTO #table2
VALUES (1, 1, 'Match for id 1'), (1, 2, 'Second match for id 1'), (1, 4, 'Match for id 1'), (2, 1, 'Match for id 2'), (2,3, 'Not a match for id 2'),  (4, 1, 'fdvg');

如您所见,id 1的所有条目都存在于两个表中。对于id 2,#Table1和#table2都具有type = 1,但类型2和3仅存在于一个表中(因此不应出现在最终结果中)。 Id 3仅存在于#table1中,因此也不会出现。 Id 4仅存在于#table2中,因此也不应该显示。

让我们首先加入关于id的表,而不考虑类型:

SELECT 
    *
FROM #table1
    JOIN #table2 ON #table1.id = #table2.id;

结果:

id  myType  columnA id  myType  columnB
1   1   aaaa    1   1   Match for id 1
1   2   aaab    1   1   Match for id 1
1   4   aaaac   1   1   Match for id 1
1   1   aaaa    1   2   Second match for id 1
1   2   aaab    1   2   Second match for id 1
1   4   aaaac   1   2   Second match for id 1
1   1   aaaa    1   4   Match for id 1
1   2   aaab    1   4   Match for id 1
1   4   aaaac   1   4   Match for id 1
2   1   bbbbb   2   1   Match for id 2
2   2   bbbbc   2   1   Match for id 2
2   1   bbbbb   2   3   Not a match for id 2
2   2   bbbbc   2   3   Not a match for id 2

正如您所看到的,这将返回两个表中存在ID的每一行的列表,而不考虑类型。这会产生一个结果集,其中类型组合跨行分割。这显然不是我们追求的目标。

下一步是添加类型,只返回两个表中都存在id和type的那些行:

SELECT 
    *
FROM #table1
    JOIN #table2 ON #table1.id = #table2.id
        AND #table1.myType = #table2.myType;

结果:

id  myType  columnA id  myType  columnB
1   1   aaaa    1   1   Match for id 1
1   2   aaab    1   2   Second match for id 1
1   4   aaaac   1   4   Match for id 1
2   1   bbbbb   2   1   Match for id 2

好多了。现在我们列出了两个表中存在的每个组合。但是,根据您的描述,您不希望看到id = 2,因为表之间的类型没有完全匹配。

上面的查询已经清除了#table1中存在的#table2中不存在的任何行(id = 2,未返回type = 2),但显然它没有考虑到#中有一行table2中不存在的table2。

我们可以通过添加一个子查询来实现这一点,该子查询列出#table1中不存在#table1中的条目的所有id:

SELECT 
    *
FROM #table1
    JOIN #table2 ON #table1.id = #table2.id
        AND #table1.myType = #table2.myType
WHERE #table1.id NOT IN 
        (
            SELECT #Table2.id FROM #Table2 
                LEFT JOIN #table1 ON #table2.id = #table1.id 
                    AND #Table2.myType = #table1.myType
            WHERE #table1.MyType IS NULL
        );

结果:

1   1   aaaa    1   1   Match for id 1
1   2   aaab    1   2   Second match for id 1
1   4   aaaac   1   4   Match for id 1

查询的开头与之前相同。但是,现在还有一个WHERE条款。后面的子查询基本上将返回和id,#table2中的id和type的组合在#table1中没有匹配的记录。

如果您要自己运行该子查询,它将返回ID 2和4(4只存在于#Table2中,其中id = 2,type = 3不在#table1中。