SQL Server:基于3个表匹配记录

时间:2019-02-21 17:35:23

标签: sql-server tsql join outer-join

我正在尝试在三个表之间匹配记录,两个表是要匹配的数据,第三个表是一个中心表,告诉我应该如何匹配记录。

一个例子将比冗长的演讲更清楚:

表1

Value1  A1  B1  C1
------------------
  0.1   1   b   z
  0.2   4   b   z
  1.1   5   b   z
  1.5   5   c   y
  2.5   7   c   x

表2

Value2  A2  B2  C2
------------------
  0.5   1   d   z
  0.7   4   d   z
  2.3   7   d   z
  1.7   5   e   y
  1.9   7   e   x

表3

    BL  BR  C
   -----------
     d   b  z
     c   e  x
     c   e  y

一种查看方式是A代表持股,C持证人和B日期。因此,表1告诉我某些日期的持仓量,表2告诉我其他日期的持仓量,最后表3告诉我如何比较持仓量,例如对于持有人C = z,我想比较日期B = d和日期B = b之间的持有量(实际上表1和2相同)。

因此,我要寻找的是一个表格,用于比较馆藏,同时考虑创建的馆藏和已删除的馆藏。我正在寻找类似的东西:

Value1 A1  B1  C1  BR BL C  A2 B2 C2 Value2
-------------------------------------------
  0.1   1   b   z   b d  z  1   d  z  0.5
  0.2   4   b   z   b d  z  4   d  z  0.7
  1.1   5   b   z   b d  z
                    b d  z  7   d  z  2.3
  1.5   5   c   y   c e  y  5   e  y  1.7
  2.5   7   c   x   c e  x  7   e  x  1.9

因此,基本上,仅当A1 = A2,C1 = C2并且B1 = BR,B2 = BL时才匹配记录,否则在一侧或另一侧为空。

我希望这很清楚。我尝试了各种方法(左/右/完全联接),但均未成功。欢迎任何帮助!

谢谢

编辑 添加示例代码。这是T-SQL。

CREATE TABLE #T1  (Value1 FLOAT, A1 INT, B1 CHAR, C1 CHAR);  
CREATE TABLE #T2 (Value2 FLOAT, A2 INT, B2 CHAR, C2 CHAR);  
CREATE TABLE #T3 (BR CHAR, BL CHAR, C CHAR);  

INSERT INTO #T1  VALUES (0.1, 1, 'b', 'z'), 
                (0.2, 4, 'b', 'z'), 
                (1.1, 5, 'b', 'z'), 
                (1.5, 5, 'c', 'y'), 
                (2.5, 7, 'c', 'x');

INSERT INTO #T2  VALUES (0.5, 1, 'd', 'z'), 
                (0.7, 4, 'd', 'z'), 
                (2.3, 7, 'd', 'z'), 
                (1.7, 5, 'e', 'y'), 
                (1.9, 7, 'e', 'x');

INSERT INTO #T3  VALUES ('b', 'd', 'z'), 
                    ('c', 'e', 'x'),
                    ('c', 'e', 'y');

我尝试过的示例查询。

SELECT 
    *
FROM #T3 
LEFT JOIN #T1 ON #T1.B1 = #T3.BR AND #T1.C1 = #T3.C
FULL JOIN #T2 ON #T2.B2 = #T3.BL AND #T2.C2 = #T3.C AND #T2.A2 = #T1.A1

这就是我得到的result。关闭,但是我希望BR,BL和C永远不要为NULL,因为在那之后我有一些逻辑。这些列不必在最后一行为空,可以将其与#T3中的一行匹配。

整个困难都在AND #T2.A2 = #T1.A1中:如果存在这样的记录,我希望它匹配,但是如果不存在,我希望它表现得好像第二个联接是#T2.B2 = #T3.BL AND #T2.C2 = #T3.C上的LEFT JOIN一样< / p>

编辑2 感谢Marlin Pierce的帖子,这是一个可以返回我寻找的结果的请求:

SELECT Value1 A1,  B1,  C1,  BR, BL, C,  A2, B2, C2, Value2
FROM #T3 inner join #T1 on #T1.B1 = #T3.BR AND #T1.C1 = #T3.C
         inner join #T2 on #T2.B2 = #T3.BL AND #T2.C2 = #T3.C AND #T2.A2 = #T1.A1

UNION ALL

SELECT Value1 A1,  B1,  C1,  BR, BL, C,  A2, B2, C2, Value2
FROM #T3 left join #T2 on #T2.B2 = #T3.BL and #T2.C2 = #T3.C
         full join #T1 on #T1.B1 = #T3.BR and #T1.C1 = #T3.C AND #T2.A2 = #T1.A1
WHERE #T1.A1 is NULL

UNION ALL

SELECT Value1 A1,  B1,  C1,  BR, BL, C,  A2, B2, C2, Value2
FROM #T3 left join #T1 on #T1.B1 = #T3.BR and #T1.C1 = #T3.C
         full join #T2 on #T2.B2 = #T3.BL and #T2.C2 = #T3.C AND #T2.A2 = #T1.A1
WHERE #T2.A2 is NULL

但是我想找到一种更有效/更优雅的方法来做到这一点,它确实存在。

1 个答案:

答案 0 :(得分:0)

我不确定,但是我认为这会为您提供所需的结果。 (您正在寻找的东西还不清楚。)

我不知道是否有一个更简单的解决方案,但可能没有,因为您正在根据内部联接的规则寻找折叠交叉组合,但是您需要一个外部联接来包含“缺失”记录。 / p>

SELECT Value1 A1,  B1,  C1,  BR, BL, C,  A2, B2, C2, Value2
FROM T3 inner join T1 on T1.B1 = T3.BR
        inner join T2 on T2.B2 = T3.BL
WHERE A1 = A2 and C1 = C2

UNION ALL

SELECT Value1 A1,  B1,  C1,  BR, BL, C,  A2, B2, C2, Value2
FROM T3 inner join T1 on T1.B1 = T3.BR
        left outer join T2 on T2.B2 = T3.BL
WHERE T2.B2 is NULL

UNION ALL

SELECT Value1 A1,  B1,  C1,  BR, BL, C,  A2, B2, C2, Value2
FROM T3 inner join T2 on T2.B2 = T3.BL
        left outer join T1 on T1.B1 = T3.BR
WHERE T1.B1 is NULL