"无效的标识符"加入我在SELECT语句中创建的列时

时间:2011-06-23 20:44:42

标签: sql oracle join case

注意:我的研究出现了this question,这为我的问题提供了一个可能的解决方案,但我的问题更为笼统:我应该采用哪种解决方案?

我想查询一个学术历史数据库,给我一个特定学生所采取的每对微积分课程的记录,其中一个是另一个的先决条件。如果数据库设置得很好或者课程编号合理,我可以这样做:

SELECT ...
FROM Academic_History PrerequisiteCourse
JOIN Academic_History NextCourse 
     ON (NextCourse.CalculusLevel = PrerequisiteCourse.CalculusLevel + 1) 
WHERE ...

当然,CalculusLevel字段不存在,所以这是无稽之谈。此外,有几个课程编号可以作为微积分I,有几个可以作为微积分II,等等,这些经常变化。这使得将所有先决条件配对硬编码到JOIN语句中,这是一个非常糟糕的主意:

SELECT ...
FROM Academic_History PrerequisiteCourse
JOIN Academic_History NextCourse 
     ON (NextCourse.CourseNumber = '231' AND PrerequisiteCourse.CourseNumber = '220'
      OR NextCourse.CourseNumber = '231' AND PrerequisiteCourse.CourseNumber = '221'
      OR NextCourse.CourseNumber = '241' AND PrerequisiteCourse.CourseNumber = '231'
      OR NextCourse.CourseNumber = '24-' AND PrerequisiteCourse.CourseNumber = '231'   
      ...)
WHERE ...

应该做的事情是动态创建我的“CalculusLevel”字段,这将更容易维护:

SELECT CASE PrerequisiteCourse.CRS_NBR
            WHEN '115' THEN '0'
            WHEN '220' THEN '1'
            WHEN '221' THEN '1' 
            ...
            END PrerequisiteCourseLevel,
       CASE NextCourse.CRS_NBR
            WHEN '115' THEN '0'
            WHEN '220' THEN '1'
            WHEN '221' THEN '1' 
            ...
            END NextCourseLevel,

FROM Academic_History PrerequisiteCourse
JOIN Academic_History NextCourse 
     ON (PrerequisiteCourseLevel + 1 = NextCourseLevel)
WHERE ...

但是当然连接不起作用,因为那些列不在那些表中。即使我将条件移出JOIN ON并进入WHERE子句,但我得到一个“无效标识符”错误,可能是因为当WHERE子句正在存在时这些字段还不存在执行。

这样做的正确方法是什么?我想出了一些像我在第二个代码块中提到的那样的解决方案,但他们都觉得不专业的黑客攻击。

谢谢!

1 个答案:

答案 0 :(得分:2)

您可以使用CTE添加可重复使用的列:

;with   hist as
        (
        select  case ... end as NextCourseLevel
        ,       case ... end as PrerequisiteCourseLevel
        ,       *
        from    Academic_History
        )
select  *
from    hist t1
join    hist t2
on      t1.PrerequisiteCourseLevel + 1 = t2.NextCourseLevel

编辑:根据您的评论,您可以通过在任何地方展开它来重构with语句:

select  *
from    (
        select  case ... end as PrerequisiteCourseLevel
        ,       *
        from    Academic_History
        ) as t1
join    (
        select  case ... end as NextCourseLevel
        ,       *
        from    Academic_History
        ) as t2
on      t1.PrerequisiteCourseLevel + 1 = t2.NextCourseLevel