【发布时间】:2014-12-10 04:01:05
【问题描述】:
在我的查询中,我有各种连接和对连接的附加限制。我要重点关注的是:
INNER JOIN PerfLevelReportBandComponents bandComponents ON bandComponents.fkPerformanceLevelReportBandID = bands.pkPerformanceLevelReportBandID
AND ((bandComponents.ScoreValue = StudentScores_Subject.ScoreValue))
OR ((CAST(StudentScores_Subject.ScoreValue AS INT) BETWEEN bandComponents.minScore and bandComponents.maxScore)
OR (CAST(StudentScores_Subject.ScoreValue AS INT) BETWEEN cutScores.minScore and cutScores.maxScore))
StudentScores_Subject.ScoreValue 列可以在bandComponents.ScoreValue、bandComponents.minScore/bandComponents.maxScore 或cutScores.minScore/cutScores.maxScore 中进行比较。如果 StudentScores_Subject.ScoreValue 是一个整数值,例如 0-99 之间的数字,则它的值可以通过这些 AND 或 ORs 中的任何一个进行比较,但我不知道它比较的是哪一个每次都取决于对问题不重要的其他限制,所以底线是我不知道它将使用哪个AND 或OR 来创建限制,所以我需要在连接中添加所有这些附加语句。通常在过去,StudentScores_Subject.ScoreValue 包含的学生分数只是数值,所以我对连接中的限制没有任何问题,但现在这些值可以是字符串,例如“FBB”(远低于基本值)甚至“ P”(通过)。现在在转换中字符串分数转换为整数时总是存在错误,但这并不一定是因为如果值是字符串,它总是给定唯一需要运行的限制是AND ((bandComponents.ScoreValue = StudentScores_Subject.ScoreValue))。所以我的问题是,有没有办法将连接中的这些额外限制转换为某种 case 语句,所以如果值是字符串,它们不会达到两秒 ORs,但如果分数值是整数,它们可以达到那些额外的限制。这是完整的查询:
SELECT MM_SchoolYears.pkSchoolYearID, TestInstances.pkTestInstanceID, StudentScores_Subject.fkTest_SubjectID, 0 AS 'fkDemographicCodeID', SUM(CASE WHEN bands.StackPosition = '0' THEN 1 ELSE 0 END) * 100.0/ CASE WHEN COUNT(pkStudentScoreID) = 0 THEN 1 ELSE COUNT(pkStudentScoreID) END AS 'Percent_0', SUM(CASE WHEN bands.StackPosition = '0' THEN 1 ELSE 0 END) AS 'Count_0', (SELECT bb.pkPerformanceLevelReportBandID FROM PerformanceLevelReportBands bb WHERE bb.fkPerformanceLevelReportID = '6' AND bb.StackPosition = '0') AS 'BandID_0', SUM(CASE WHEN bands.StackPosition = '1' THEN 1 ELSE 0 END) * 100.0/ CASE WHEN COUNT(pkStudentScoreID) = 0 THEN 1 ELSE COUNT(pkStudentScoreID) END AS 'Percent_1', SUM(CASE WHEN bands.StackPosition = '1' THEN 1 ELSE 0 END) AS 'Count_1', (SELECT bb.pkPerformanceLevelReportBandID FROM PerformanceLevelReportBands bb WHERE bb.fkPerformanceLevelReportID = '6' AND bb.StackPosition = '1') AS 'BandID_1'
FROM StudentScores_Subject
INNER JOIN StudentTests ON StudentScores_Subject.fkStudentTestID = StudentTests.pkStudentTestID
INNER JOIN TestInstances ON TestInstances.pkTestInstanceID = StudentTests.fkTestInstanceID
INNER JOIN CAHSEE_TestPeriods ON CAHSEE_TestPeriods.pkTestPeriodID = TestInstances.fkTestPeriodID
INNER JOIN PerformanceLevelReportBands bands ON bands.fkPerformanceLevelReportID = @intPerfLevelReportId
LEFT JOIN MMARS_Web_TestInfo_California.dbo.PerfLevelReportBandCutScores cutScores ON cutScores.fkPerformanceLevelReportBandID = bands.pkPerformanceLevelReportBandID
AND cutScores.fkGradeID = @intGradeId
AND cutScores.fkTestSubjectID IN (SELECT id FROM @tempSubs)
INNER JOIN PerfLevelReportBandComponents bandComponents ON bandComponents.fkPerformanceLevelReportBandID = bands.pkPerformanceLevelReportBandID
AND ((bandComponents.ScoreValue = StudentScores_Subject.ScoreValue))
OR ((CAST(StudentScores_Subject.ScoreValue AS INT) BETWEEN bandComponents.minScore and bandComponents.maxScore)
OR (CAST(StudentScores_Subject.ScoreValue AS INT) BETWEEN cutScores.minScore and cutScores.maxScore))
RIGHT JOIN MM_SchoolYears ON MM_SchoolYears.pkSchoolYearID = TestInstances.fkSchoolYearID
WHERE MM_SchoolYears.pkSchoolYearID IN (SELECT number FROM itot(@strYearIds, N','))
AND bands.fkPerformanceLevelReportID = @intPerfLevelReportId
AND StudentScores_Subject.fkStudentTestID IN (SELECT id FROM @tempTests)
AND StudentScores_Subject.fkScoreTypeID = bandComponents.fkScoreTypeID
AND StudentScores_Subject.fkTest_SubjectID IN (SELECT id FROM @tempSubs)
AND (bandComponents.ScoreValue = StudentScores_Subject.ScoreValue)
GROUP BY MM_SchoolYears.pkSchoolYearID, TestInstances.pkTestInstanceID, StudentScores_Subject.fkTest_SubjectID
ORDER BY MM_SchoolYears.pkSchoolYearID, TestInstances.pkTestInstanceID, StudentScores_Subject.fkTest_SubjectID
长选择语句是动态创建的,只是为学生集创建计数和百分比,但对问题不重要。
【问题讨论】:
-
您可以将它们转换为案例,但考虑到查询的复杂性,我认为您最好还是预先计算结果(有一份工作,这样您就可以更轻松地查询结果)或尝试将其拆分为多个查询,一起进行联合;只是为了摆脱“或”逻辑,这很容易对 sql 中的执行计划造成严重破坏
标签: sql-server join case