对不起SQL的问题,但我在下面的查询中遇到了一些问题。它似乎永远不会完成执行(它运行几分钟,然后我杀了它)。奇怪的是,如果我将StudentTestsPre表的连接条件从 TestInstances.fkSchoolYearID =(TestInstancesPre.fkSchoolYearID + 1)更改为 TestInstances.fkSchoolYearID> TestInstancesPre.fkSchoolYearID ,然后查询立即返回。如何使用更独特的连接条件导致我的查询挂起?似乎这样可以使查询更快,如果有的话。
有什么想法吗?
SELECT *
FROM TestInstances
INNER JOIN StudentTests on StudentTests.fkTestInstanceID = TestInstances.pkTestInstanceID
AND StudentTests.pkStudentTestID IN (SELECT * FROM @tempTests)
INNER JOIN TestInstances TestInstancesPre ON TestInstances.fkSchoolYearID = (TestInstancesPre.fkSchoolYearID + 1)
AND TestInstancesPre.fkTestTypeID = 1 AND TestInstances.fkTestTypeID = 1
INNER JOIN StudentTests StudentTestsPre on StudentTestsPre.fkTestInstanceID = TestInstancesPre.pkTestInstanceID
AND StudentTests.fkStudentID = StudentTestsPre.fkStudentID
INNER JOIN StudentScores_Subject s ON s.fkStudentTestID = StudentTests.pkStudentTestID
AND s.fkTest_SubjectID IN (SELECT pkTestSubjectID FROM MM_Test_Subjects WHERE fkCSTStrandID IN (SELECT number FROM itot(@strAcceptableStrands, N',')) AND fkTestTypeID = 1)
AND s.fkScoreTypeID = 3
INNER JOIN StudentScores_Subject sPre ON sPre.fkStudentTestID = StudentTestsPre.pkStudentTestID
AND sPre.fkTest_SubjectID IN (SELECT pkTestSubjectID FROM MM_Test_Subjects WHERE fkCSTStrandID IN (SELECT number FROM itot(@strAcceptableStrands, N',')) AND fkTestTypeID = 1)
AND sPre.fkScoreTypeID = 3
INNER JOIN MM_Test_PL_SS_Ranges r ON r.fkTest_SubjectID = s.fkTest_SubjectID
AND r.fkSchoolYearID = TestInstances.fkSchoolYearID
AND r.fkTestTypeID = TestInstances.fkTestTypeID
AND (r.fkGradeID = StudentTests.fkGradeID OR r.fkGradeID = 99)
INNER JOIN MM_Test_PL_SS_Ranges rPre ON rPre.fkTest_SubjectID = sPre.fkTest_SubjectID
AND rPre.fkSchoolYearID = TestInstancesPre.fkSchoolYearID
AND rPre.fkTestTypeID = TestInstancesPre.fkTestTypeID
AND (rPre.fkGradeID = StudentTestsPre.fkGradeID OR rPre.fkGradeID = 99)
INNER JOIN StudentScores_Subject s2 ON s2.fkStudentTestID = StudentTests.pkStudentTestID
AND s2.fkTest_SubjectID = s.fkTest_SubjectID
AND s2.fkScoreTypeID = 2
INNER JOIN StudentScores_Subject sPre2 ON sPre2.fkStudentTestID = StudentTestsPre.pkStudentTestID
AND sPre2.fkTest_SubjectID = sPre.fkTest_SubjectID
AND sPre2.fkScoreTypeID = 2
INNER JOIN Students on Students.pkStudentID = StudentTests.fkStudentID
感谢您的帮助!
对于SO,这是上面的脚本与替代格式&短别名:
SELECT *
FROM TestInstances
INNER JOIN StudentTests st
ON st.fkTestInstanceID = ti.pkTestInstanceID
AND st.pkStudentTestID IN (SELECT * FROM @tempTests)
INNER JOIN TestInstances tiPre
ON ti.fkSchoolYearID = (tiPre.fkSchoolYearID + 1)
AND tiPre.fkTestTypeID = 1 AND ti.fkTestTypeID = 1
INNER JOIN StudentTests stPre
ON stPre.fkTestInstanceID = tiPre.pkTestInstanceID
AND st.fkStudentID = stPre.fkStudentID
INNER JOIN StudentScores_Subject s
ON s.fkStudentTestID = st.pkStudentTestID
AND s.fkTest_SubjectID IN (
SELECT pkTestSubjectID
FROM MM_Test_Subjects
WHERE fkCSTStrandID IN (
SELECT number FROM itot(@strAcceptableStrands, N','))
AND fkTestTypeID = 1)
AND s.fkScoreTypeID = 3
INNER JOIN StudentScores_Subject sPre
ON sPre.fkStudentTestID = stPre.pkStudentTestID
AND sPre.fkTest_SubjectID IN (
SELECT pkTestSubjectID
FROM MM_Test_Subjects
WHERE fkCSTStrandID IN (
SELECT number FROM itot(@strAcceptableStrands, N','))
AND fkTestTypeID = 1)
AND sPre.fkScoreTypeID = 3
INNER JOIN MM_Test_PL_SS_Ranges r
ON r.fkTest_SubjectID = s.fkTest_SubjectID
AND r.fkSchoolYearID = ti.fkSchoolYearID
AND r.fkTestTypeID = ti.fkTestTypeID
AND (r.fkGradeID = st.fkGradeID OR r.fkGradeID = 99)
INNER JOIN MM_Test_PL_SS_Ranges rPre
ON rPre.fkTest_SubjectID = sPre.fkTest_SubjectID
AND rPre.fkSchoolYearID = tiPre.fkSchoolYearID
AND rPre.fkTestTypeID = tiPre.fkTestTypeID
AND (rPre.fkGradeID = stPre.fkGradeID OR rPre.fkGradeID = 99)
INNER JOIN StudentScores_Subject s2
ON s2.fkStudentTestID = st.pkStudentTestID
AND s2.fkTest_SubjectID = s.fkTest_SubjectID
AND s2.fkScoreTypeID = 2
INNER JOIN StudentScores_Subject sPre2
ON sPre2.fkStudentTestID = stPre.pkStudentTestID
AND sPre2.fkTest_SubjectID = sPre.fkTest_SubjectID
AND sPre2.fkScoreTypeID = 2
INNER JOIN Students
ON Students.pkStudentID = st.fkStudentID
答案 0 :(得分:4)
看看你的执行计划。我的猜测是,在连接又名(TestInstancesPre.fkSchoolYearID + 1)
中进行计算会导致索引无法正确使用。一种简单的测试方法是将您的联接更改为:
TestInstances.fkSchoolYearID = TestInstancesPre.fkSchoolYearID
在连接中做一些时髦的东西时,我看到性能下降了。比如:
ON t1.column1 = ISNULL(t2.myColumn, 1)
我相信这是因为查询变得不可思议。有关详细信息,请查看this SO post。
答案 1 :(得分:0)
通过比较计算,它可以使索引的使用无效。当计算结果的数据类型与要编制索引的列的数据类型不同时,通常会发生这种情况。如果必须重复足够次数(例如,来自大量连接),有时计算成本很高。一种解决方案是将计算值存储在特殊列中,例如:
CREATE TABLE TestInstances (
...
nextSchoolYearID int);
使用触发器或逻辑来维护nextSchoolYearID = fkSchoolYearID + 1
,然后使用
ON TestInstances.fkSchoolYearID = TestInstancesPre.nextSchoolYearID)
此外,您在第一个联接的AND StudentTests.pkStudentTestID IN (SELECT * FROM @tempTests)
子句中有on
,但@tempTests中的值与这两个表都无关。
尝试将该谓词移动到最后的where子句,即:
SELECT
...
WHERE StudentTests.pkStudentTestID IN (SELECT * FROM @tempTests)
这样做意味着SELECT * FROM @tempTests
只会执行一次,而不是针对TestInstances和StudentTests的每一行组合执行。