Sql 将表1连接到表2中的第1列或第2列,但不重复
[MS SQL 2008] 我有表(所有列都是字符串名称): A:将某个数据字段与所属实体关联的两列 B:定义实体层次结构的三列 我需要创建整个层次结构的单个表(包括两个表中不存在的所有行),但表a中的键列(显示为Acol2)可以位于表B的第1列或第2列中Sql 将表1连接到表2中的第1列或第2列,但不重复,sql,sql-server,sql-server-2008,Sql,Sql Server,Sql Server 2008,[MS SQL 2008] 我有表(所有列都是字符串名称): A:将某个数据字段与所属实体关联的两列 B:定义实体层次结构的三列 我需要创建整个层次结构的单个表(包括两个表中不存在的所有行),但表a中的键列(显示为Acol2)可以位于表B的第1列或第2列中 A: B: Acol1 | Acol2 Bcol1 | Bcol2 | Bcol3 -------+------ --------+--
A: B:
Acol1 | Acol2 Bcol1 | Bcol2 | Bcol3
-------+------ --------+-------+------
A | B B | X | Y
C | D Q | X | Y
E | F H | D | Z
G | H W | V | U
输出应该是
Hierarchy:
Acol1 | Bcol1 | Bcol2 | Bcol3
-------+-------+-------+------
A | B | X | Y
Null | Q | X | Y
C | Null | D | Z
G | H | D | Z
E | Null | Null | Null
Null | W | V | U
Logic (also added to original):
If A has no record in B, show A with all Null
If A has record in Bcol1, show A with full row B
If A has record in Bcol2, show A with Null, Bcol2, Bcol3
If B has no record in A, show B with Null for Acol1
我尝试过两个独立连接的各种联合,但似乎无法摆脱无关的行
B在Acol2=Bcol1上左连接A联合B在Acol2=Bcol2上左连接A代码>
给出重复的行,因为联合的第二部分必须将Bcol1设置为NULL
(可能有一种解决方案是删除此重复的空行?)
B内部联接A在Acol2=Bcol1上的联合B内部联接A在Acol2=Bcol2上的联合代码>
显然,删除A和B中没有共享键的所有行
(关于仅恢复这些行的简单方法的解决方案?)
SELECT
Table1.ACol1,
CASE WHEN Table1.ACol1 = Table2.BCol1 THEN Table2.BCol1 ELSE NULL END AS BCol1
Table2.BCol2,
Table2.BCol3
FROM
Table1
FULL OUTER JOIN
Table2
ON Table1.ACol2 IN (Table2.BCol1, Table2.BCol2)
当您说无重复项
时,只有当ACol2
仅出现在表2中一行的一个字段中时,才可能出现这种情况。如果它出现在多个地方,您将得到重复。-如果可能的话,您希望如何从表2中选择哪个记录
然而,一般来说,这是一种SQL反模式 这是因为联接更喜欢表2中的索引。但是,由于您永远不知道要加入哪个字段,因此没有一个索引能够满足加入条件
编辑: 创建一个标准化的表格B将大大加快这一速度
B_ID | B_Col | B_Val
------+-------+-------
1 | 1 | B
1 | 2 | X
1 | 3 | Y
2 | 1 | Q
2 | 2 | X
2 | 3 | Y
3 | 1 | H
3 | 2 | D
3 | 3 | Z
4 | 1 | W
4 | 2 | V
4 | 3 | U
然后用(B_ID)
和(B_Val)
索引该表
然后将B_ID
字段包括在非标准化表格中
ID | Bcol1 | Bcol2 | Bcol3
------+-------+-------+-------
1 | B | X | Y
2 | Q | X | Y
3 | H | D | Z
4 | W | V | U
然后使用以下查询
SELECT
Table1.ACol1,
CASE WHEN Table1.ACol1 = Table2.BCol1 THEN Table2.BCol1 ELSE NULL END AS BCol1
Table2.BCol2,
Table2.BCol3
FROM
(
Table1
LEFT JOIN
Table2Normalised
ON Table2Normalised.B_Val = Table1.ACol2
AND Table2Normalised.B_Col IN (1,2)
)
FULL OUTER JOIN
Table2
ON Table2Normalised.B_ID = Table2.ID
编辑: 不更改模式,而是在BCol1上有一个索引,在Bcol2上有第二个索引
SELECT ACol1, BCol1, BCol2, BCol3 FROM Table1 a INNER JOIN Table2 b ON a.ACol2 = b.BCol1
UNION ALL
SELECT ACol1, NULL, BCol2, BCol3 FROM Table1 a INNER JOIN Table2 b ON a.ACol2 = b.BCol2
UNION ALL
SELECT ACol1, NULL, NULL, NULL FROM Table1 a WHERE NOT EXISTS (SELECT * FROM Table2 WHERE BCol1 = a.ACol2)
AND NOT EXISTS (SELECT * FROM Table2 WHERE BCol2 = a.ACol2)
UNION ALL
SELECT NULL, BCol1, BCol2, BCol3 FROM Table2 b WHERE NOT EXISTS (SELECT * FROM Table1 WHERE ACol2 = b.BCol1)
AND NOT EXISTS (SELECT * FROM Table1 WHERE ACol2 = b.BCol2)
但那太乱了
当您说无重复项
时,只有当ACol2
仅出现在表2中一行的一个字段中时,才可能出现这种情况。如果它出现在多个地方,您将得到重复。-如果可能的话,您希望如何从表2中选择哪个记录
然而,一般来说,这是一种SQL反模式 这是因为联接更喜欢表2中的索引。但是,由于您永远不知道要加入哪个字段,因此没有一个索引能够满足加入条件
编辑: 创建一个标准化的表格B将大大加快这一速度
B_ID | B_Col | B_Val
------+-------+-------
1 | 1 | B
1 | 2 | X
1 | 3 | Y
2 | 1 | Q
2 | 2 | X
2 | 3 | Y
3 | 1 | H
3 | 2 | D
3 | 3 | Z
4 | 1 | W
4 | 2 | V
4 | 3 | U
然后用(B_ID)
和(B_Val)
索引该表
然后将B_ID
字段包括在非标准化表格中
ID | Bcol1 | Bcol2 | Bcol3
------+-------+-------+-------
1 | B | X | Y
2 | Q | X | Y
3 | H | D | Z
4 | W | V | U
然后使用以下查询
SELECT
Table1.ACol1,
CASE WHEN Table1.ACol1 = Table2.BCol1 THEN Table2.BCol1 ELSE NULL END AS BCol1
Table2.BCol2,
Table2.BCol3
FROM
(
Table1
LEFT JOIN
Table2Normalised
ON Table2Normalised.B_Val = Table1.ACol2
AND Table2Normalised.B_Col IN (1,2)
)
FULL OUTER JOIN
Table2
ON Table2Normalised.B_ID = Table2.ID
编辑: 不更改模式,而是在BCol1上有一个索引,在Bcol2上有第二个索引
SELECT ACol1, BCol1, BCol2, BCol3 FROM Table1 a INNER JOIN Table2 b ON a.ACol2 = b.BCol1
UNION ALL
SELECT ACol1, NULL, BCol2, BCol3 FROM Table1 a INNER JOIN Table2 b ON a.ACol2 = b.BCol2
UNION ALL
SELECT ACol1, NULL, NULL, NULL FROM Table1 a WHERE NOT EXISTS (SELECT * FROM Table2 WHERE BCol1 = a.ACol2)
AND NOT EXISTS (SELECT * FROM Table2 WHERE BCol2 = a.ACol2)
UNION ALL
SELECT NULL, BCol1, BCol2, BCol3 FROM Table2 b WHERE NOT EXISTS (SELECT * FROM Table1 WHERE ACol2 = b.BCol1)
AND NOT EXISTS (SELECT * FROM Table1 WHERE ACol2 = b.BCol2)
但这太麻烦了…你能为我们创建一个sql提琴吗?你能为我们创建一个sql提琴吗?效率有多低?@Woot4Moo-我同意,但我没有设计模式或功能需求。没错,只是等着手术给我们一个机会fiddle@Woot4Moo-我是为他做的:-)我不知道小提琴-从中学到的有用的东西,如果没有别的!这有多低效?@Woot4Moo-我同意,但我没有设计模式或功能需求。没错,只是等待OP给我们一个答案fiddle@Woot4Moo-我是为他做的:-)我不知道小提琴-从中学到的有用的东西,如果没有别的!