[MS SQL 2008]
我有表(所有列都是字符串名称): 答:两个列将一些数据字段与一个拥有实体相关联 B:定义实体层次结构的三列
我需要创建整个层次结构的单个表(包括两个表中不存在的所有行),但表A中的键列(显示为Acol2)可以位于表B的第1列或第2列中。
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
我尝试了两种不同的JOIN的各种UNION,但似乎无法摆脱多余的行......
B LEFT JOIN A ON Acol2=Bcol1 UNION B LEFT JOIN A ON Acol2=Bcol2;
给出重复的行,因为union的第二部分必须将Bcol1设置为NULL
(也许一种解决方案是删除这个重复的NULL行的方法?)B INNER JOIN A ON Acol2=Bcol1 UNION B INNER JOIN A ON Acol2=Bcol2;
显然,从A和B中删除没有共享密钥的所有行
(关于重新获得那些行的简单方法的解决方案?)任何想法都赞赏!
玩: [SQL已删除 - 请参阅回复评论中的小提琴]
答案 0 :(得分:4)
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)
当您说no duplicates
时,仅当ACol2
仅出现在Table2中的一行的一个字段中时,才可能这样做。如果它出现在多个地方,您将获得重复
- 如果可能的话,你想如何从Table2中选择哪条记录?
此外,一般情况下,这是一个SQL-Anti-Pattern。
这是因为联接更喜欢Table2上的索引。但是,既然你永远不知道你加入了哪个领域,那么任何一个索引都不会对连接条件产生影响。
的修改:
使这个显着更快的原因是创建一个标准化的TableB ...
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)
...
然后在non_normalised表中包含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)
但那太乱了......