将join子句中的其他要求更改为case语句

时间:2014-12-10 04:01:06

标签: sql-server join case

在我的查询中,我对连接有各种连接和其他限制。我想关注的是:

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.ScoreValuebandComponents.ScoreValue / bandComponents.minScorebandComponents.maxScore / cutScores.minScore中比较专栏cutScores.maxScore。如果StudentScores_Subject.ScoreValue是一个整数值,例如介于0-99之间的数字,则可以通过这些ANDOR中的任何一个来比较该值,但我赢了“根据对问题不重要的其他限制,我知道每次比较哪一个,所以底线是我不知道它将用于创建限制的ANDOR,所以我需要在连接中添加所有这些附加语句。通常在过去,StudentScores_Subject.ScoreValue包含学生分数,这些分数只是数值,所以我对连接中的限制没有问题,但现在值可以是字符串,例如“FBB”(远低于基本)或甚至“P”(通过)。现在总是有一个错误,字符串分数在转换中转换为整数,但这不是必须的,因为如果值是一个字符串,那么它总是给定的唯一限制是AND ((bandComponents.ScoreValue = StudentScores_Subject.ScoreValue))。所以我的问题是,有没有办法将连接中的这些额外限制转换为某种case语句,所以如果值是字符串,它们将不会达到两秒OR s,但如果得分值是整数他们可以达到这些额外的限制。以下是完整查询:

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

长选择语句是动态创建的,只是为学生集创建计数和百分比,但对问题不重要。

1 个答案:

答案 0 :(得分:1)

您可以通过添加ISNUMERIC检查来扩展连接条件,如下所示:

INNER JOIN PerfLevelReportBandComponents bandComponents ON bandComponents.fkPerformanceLevelReportBandID = bands.pkPerformanceLevelReportBandID 
  AND ((bandComponents.ScoreValue = StudentScores_Subject.ScoreValue))
  OR
  (
    ISNUMERIC(StudentScores_Subject.ScoreValue)
    AND
    (
      (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)
    )
   )

这不是万无一失的 - 有很多讨论为什么ISNUMERIC不保证CAST到int的工作方式或其他方式,但在你的情况下,它可能足以解决你的问题。