如何使这个缓慢的嵌套SQL Case Query更快

时间:2016-11-02 23:30:14

标签: sql sql-server

我有一个'联系人'表,其中包括姓名,姓氏,DOB等字段。

我正在尝试创建一个SQL视图,其中还包含一个名为“ProspectiveNews”的字段。该字段基本上包含4个分类代码(或空白)中的一个,具体取决于另一个视图中的条件匹配。

联系人可以在另一个具有不同年级的视图中拥有大量记录。

在此其他视图中,联系人ID可以出现在两列中的一列中:[ContactID]或[ContactSpouseID],其中另一列,ReferenceTable<> '询价'

然后有一些记录,其中ReferenceTable ='Inquiry',其中ContactID列包含其EnquiryID,因此需要使用它。

因此,对每个分类代码进行3次检查。

这是代码虽然需要大约2分钟才能运行。这就是问题 - 它太慢了。我能做些什么才能让这个更快?

代码摘要:

如果联系人有来自另一个视图的记录,那么只有年级0那么'K'

如果联系人有来自另一个视图的记录,那么只有年级1-6那么'1-6'

如果联系人有一个记录形成另一个视图,是年级7-12那么'7-12'

如果联系人拥有年级中的记录:

0和1-6

OR

0和7-12

OR

1-6和7-12

然后'将军'

代码:

SELECT

C.ID as ContactID,
ESC.ID as EnquiryID,

CASE WHEN	(	C.ID in		(SELECT  [ContactID]  FROM [Table] WHERE [EnrolDate] > '2016-12-31' AND YearLevel = 0 AND ReferenceTable <> 'Enquiry')
			AND NOT EXISTS	(SELECT  [ContactID]  FROM [Table] WHERE [EnrolDate] > '2016-12-31' AND YearLevel > 0 AND ReferenceTable <> 'Enquiry' AND [ContactID] = C.ID)
			)
			OR
			(	C.ID in		(SELECT  [ContactSpouseID]  FROM [Table] WHERE [EnrolDate] > '2016-12-31' AND YearLevel = 0 AND ReferenceTable <> 'Enquiry')
			AND NOT EXISTS	(SELECT  [ContactSpouseID]  FROM [Table] WHERE [EnrolDate] > '2016-12-31' AND YearLevel > 0 AND ReferenceTable <> 'Enquiry' AND [ContactSpouseID] = C.ID)
			)
			OR
			(	ESC.ContactEnquiryID in		(SELECT  [ContactID]  FROM [Table] WHERE [EnrolDate] > '2016-12-31' AND YearLevel = 0 AND ReferenceTable = 'Enquiry')
			AND NOT EXISTS  (SELECT  [ContactID]  FROM [Table] WHERE [EnrolDate] > '2016-12-31' AND YearLevel > 0 AND ReferenceTable = 'Enquiry' AND [ContactID] = C.ID)
			)
 THEN 'K' 

 ELSE 

CASE WHEN	(	C.ID in		(SELECT  [ContactID]  FROM [Table] WHERE [EnrolDate] > '2016-12-31' AND YearLevel > 0 AND YearLevel < 7 AND ReferenceTable <> 'Enquiry')
			AND NOT EXISTS	(SELECT  [ContactID]  FROM [Table] WHERE [EnrolDate] > '2016-12-31' AND YearLevel = 0 AND ReferenceTable <> 'Enquiry' AND [ContactID] = C.ID)
			AND NOT EXISTS	(SELECT  [ContactID]  FROM [Table] WHERE [EnrolDate] > '2016-12-31' AND YearLevel > 6 AND ReferenceTable <> 'Enquiry' AND [ContactID] = C.ID)
			)
			OR
			(	C.ID in		(SELECT  [ContactSpouseID]  FROM [Table] WHERE [EnrolDate] > '2016-12-31' AND YearLevel > 0 AND YearLevel < 7 AND ReferenceTable <> 'Enquiry')
			AND NOT EXISTS	(SELECT  [ContactSpouseID]  FROM [Table] WHERE [EnrolDate] > '2016-12-31' AND YearLevel = 0 AND ReferenceTable <> 'Enquiry' AND [ContactSpouseID] = C.ID)
			AND NOT EXISTS	(SELECT  [ContactSpouseID]  FROM [Table] WHERE [EnrolDate] > '2016-12-31' AND YearLevel > 6 AND ReferenceTable <> 'Enquiry' AND [ContactSpouseID] = C.ID)
			)
			OR
			(	ESC.ContactEnquiryID in		(SELECT  [ContactID]  FROM [Table] WHERE [EnrolDate] > '2016-12-31' AND YearLevel > 0 AND YearLevel < 7 AND ReferenceTable = 'Enquiry')
			AND NOT EXISTS	(SELECT  [ContactID]  FROM [Table] WHERE [EnrolDate] > '2016-12-31' AND YearLevel = 0 AND ReferenceTable = 'Enquiry' AND [ContactID] = C.ID)
			AND NOT EXISTS	(SELECT  [ContactID]  FROM [Table] WHERE [EnrolDate] > '2016-12-31' AND YearLevel > 6 AND ReferenceTable = 'Enquiry' AND [ContactID] = C.ID)
			)
			
 THEN '1-6' 

  ELSE 

CASE WHEN	(	C.ID in		(SELECT  [ContactID]  FROM [Table] WHERE [EnrolDate] > '2016-12-31' AND YearLevel > 6 AND YearLevel < 13 AND ReferenceTable <> 'Enquiry')
			AND NOT EXISTS	(SELECT  [ContactID]  FROM [Table] WHERE [EnrolDate] > '2016-12-31' AND YearLevel < 7 AND ReferenceTable <> 'Enquiry' AND [ContactID] = C.ID)
			)
			OR
			(	C.ID in		(SELECT  [ContactSpouseID]  FROM [Table] WHERE [EnrolDate] > '2016-12-31' AND YearLevel > 6 AND YearLevel < 13 AND ReferenceTable <> 'Enquiry')
			AND NOT EXISTS	(SELECT  [ContactSpouseID]  FROM [Table] WHERE [EnrolDate] > '2016-12-31' AND YearLevel < 7 AND ReferenceTable <> 'Enquiry' AND [ContactSpouseID] = C.ID)
			)
			OR
			(	ESC.ContactEnquiryID in		(SELECT  [ContactSpouseID]  FROM [Table] WHERE [EnrolDate] > '2016-12-31' AND YearLevel > 6 AND YearLevel < 13 AND ReferenceTable = 'Enquiry')
			AND NOT EXISTS	(SELECT  [ContactSpouseID]  FROM [Table] WHERE [EnrolDate] > '2016-12-31' AND YearLevel < 7 AND ReferenceTable = 'Enquiry' AND [ContactID] = C.ID)
			)
 THEN '7-6' 

  ELSE 

CASE WHEN	(	C.ID in		(SELECT  [ContactID]  FROM [Table] WHERE [EnrolDate] > '2016-12-31' AND ReferenceTable <> 'Enquiry')
			)
			OR
			(	C.ID in		(SELECT  [ContactSpouseID]  FROM [Table] WHERE [EnrolDate] > '2016-12-31' AND ReferenceTable <> 'Enquiry')
			)
			OR
			(	ESC.ContactEnquiryID in		(SELECT  [ContactID]  FROM [Table] WHERE [EnrolDate] > '2016-12-31' AND ReferenceTable = 'Enquiry')
			)

 THEN 'General'

  ELSE ''  END END

	END 
END AS ProspectiveNews

3 个答案:

答案 0 :(得分:0)

创建索引以便引擎可以优化这些子查询应该创造奇迹。您应该尝试创建这些多个索引:

ContactID + ReferenceTable + YearLevel + EnrolDate
ContactSpouseID + ReferenceTable + YearLevel + EnrolDate
ReferenceTable + YearLevel + EnrolDate
ReferenceTable + EnrolDate

答案 1 :(得分:0)

@UV

谢谢:性能缓慢是因为您从[Table]中选择了太多次。相反,加入[table]的候选名单,可能聚合,并使用连接字段的用例。如果我有时间,我稍后会写一个例子。如果你需要你加入推荐主表你可能想要使用OUTER APPLY有来自Itzik Ben-Gan的好帖子或者看这里:sqlbits.com/Sessions/Event14 / ... - UV

答案 2 :(得分:0)

性能缓慢是因为您从[表]中选择了太多次。相反,加入[table]的候选名单,可能聚合,并使用连接字段的用例。如果我有时间,我稍后会写一个例子。如果你需要你加入推荐主表你可能想要使用OUTER APPLY有来自Itzik Ben-Gan的好帖子或者看这里:sqlbits.com/Sessions/Event14 / ... - UV

Tahnk you @SSS