查询性能改进

Query Performance Improvement

这里有两个表格以不同的方式(Grp 和 Cat)对相同的项目(TBL1.ID 和 TBL2.Code)进行分类

每个Item只属于一个组(两个表中组名不同) 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

感谢任何具有更好性能的解决方案。

原始子查询有一个主要缺陷:它被设计为能够 return 多个值,但这会破坏整个查询。更改您的数据,以便任何组都连接到多个类别,并且它将失败(例如 (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 的操作更轻量级,而结果相同。