sql-server - SQL Server:基于 3 个表匹配记录
问题描述
我正在尝试匹配三个表之间的记录,两个表是要匹配的数据,第三个表是一个中央表,告诉我应该如何匹配记录。
一个例子会比长篇演讲更清楚:
表格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
这就是我得到的结果。关闭,但我希望 BR、BL 和 C 永远不会为 NULL,因为在那之后我在这些列上有一些逻辑。这些列的最后一行不必为空,它可以与#T3 中的一行匹配。
整个困难在于AND #T2.A2 = #T1.A1
:如果存在这样的记录,我希望它匹配,但如果没有,我希望它表现得好像第二个连接是左连接#T2.B2 = #T3.BL AND #T2.C2 = #T3.C
编辑 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
但是我想找到一种更有效/更优雅的方式来做到这一点,它存在。
解决方案
我不确定,但我认为这会给你你正在寻找的结果。(你在找什么有点不清楚。)
我不知道是否有更简单的解决方案,但可能没有,因为您正在通过内部连接的规则寻找折叠交叉组合,但您需要外部连接来包含“缺失”记录。
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
推荐阅读
- angular - PrimeNg TurboTable 将表格划分为单个组件
- c++ - 通过引用将数组传递给函数
- html - CSS 中的活动类
- java - 对于没有数组的 java 编程,我可以使用什么代码来表示最小值、最大值和平均值?
- java - Hybris ProductModel 类
- google-app-engine - Google Cloud .NET Core 发布启用服务
- r - 如何在 R 的另一列中选择最多一列而不是 NA?
- database - PostgresSQL/pgAdmin4/dump 服务器版本不匹配
- angular - 如何从内部元素关闭/关闭 Angular Snackbar 元素
- user-interface - 旋转加工后的位置变化