这里有两个表以不同的方式(Grp和Cat)对同一项目(TBL1.ID和TBL2.Code)进行分类
每个项目仅属于一个组(两个表中的组名不同) TBL2中的项目是TBL1中项目的子集
TBL2中仅现有猫的遗失物品,需要适当的猫。(不需要A4)
TBL1:
Grp ID
--------------------
X1 A1
X1 B1
X1 C1
X1 D1
X2 A2
X2 B2
X2 C2
X2 D2
X3 A3
X3 B3
X4 A4
TBL2:
Cat Code
--------------------
1 A1
1 B1
1 C1
2 A2
2 B2
3 A3
5 A5
所需:
ID Grp Cat
---------------------------------
D1 X1 1
C2 X2 2
D2 X2 2
B3 X3 3
此查询工作正常,但对于大量记录来说太慢了:
SELECT
TBL1.ID
,TBL1.Grp
,(SELECT DISTINCT T2.Cat FROM TBL2 T2 WHERE T2.Code IN
(SELECT T1.ID FROM TBL1 T1 WHERE T1.Grp = TBL1.Grp )) AS Cat
FROM TBL1
LEFT JOIN TBL2
ON TBL1.ID = TBL2.Code
WHERE TBL2.Code IS NULL
AND (SELECT DISTINCT T2.Cat FROM TBL2 T2 WHERE T2.Code IN
(SELECT T1.ID FROM TBL1 T1 WHERE T1.Grp = TBL1.Grp )) IS NOT NULL
任何具有更好性能的解决方案都是值得赞赏的。
答案 0 :(得分:2)
原始子查询有一个主要缺陷:它被设计为能够返回多个值,但这会破坏整个查询。更改数据,以使任何组都连接到多个类别,并且该类别将失败(例如(1, 'A1') -> (2, 'A1')
)。 DISTINCT
确实可以帮助您避免使用给定的样本数据而失败,但无法帮助您避免使用不同的值。
如果没有多个匹配组,则没有指定要选择的类别。我使用了MAX
:
SELECT
t.ID
,t.Grp
,c.Cat
FROM TBL1 t
INNER JOIN (
SELECT g.Grp, MAX(c.Cat) Cat
FROM TBL1 g
INNER JOIN TBL2 c
ON c.Code = g.ID
GROUP BY g.Grp
) c
ON c.Grp = t.Grp
WHERE NOT EXISTS(SELECT 1 FROM TBL2 t2 WHERE t2.Code = t.ID)
此处TBL1
已加入连接到任何类别的所有组的列表。 INNER JOIN
将仅保留与至少一个类别(相当于您的NOT NULL
)相关的组。我将您的LEFT JOIN
替换为NOT EXISTS
,因为它对SQL SERVER的操作更轻巧,而结果却相同。