子查询中出现意外行为

时间:2013-08-06 13:47:57

标签: sql oracle correlated-subquery

我有一个如下所示的查询:

SELECT 'FY2000' AS FY, COUNT(DISTINCT SGBSTDN_PIDM) AS CHEM_MAJORS
FROM SATURN.SGBSTDN, SATURN.SFRSTCR
WHERE SGBSTDN_PIDM = SFRSTCR_PIDM
  AND SGBSTDN_TERM_CODE_EFF = (SELECT MAX(SGBSTDN_TERM_CODE_EFF)
                               FROM SATURN.SGBSTDN
                               WHERE SGBSTDN_TERM_CODE_EFF <=  '200002'
                                 AND SGBSTDN_PIDM = SFRSTCR_PIDM)
  AND SGBSTDN_MAJR_CODE_1 = 'CHEM'
  AND SFRSTCR_TERM_CODE BETWEEN '199905' AND '200002'
  AND (SFRSTCR_RSTS_CODE LIKE 'R%' OR SFRSTCR_RSTS_CODE LIKE 'W%')
  AND SFRSTCR_CREDIT_HR >= 1

它返回48的计数,我认为是正确的。但是,我不明白为什么子查询在FROM子句中不需要SATURN.SFRSTCR以引用SFRSTCR_PIDM。我认为子查询是自包含的,无法看到查询的其余部分?

但是,如果我将SATURN.SFRSTCR添加到子查询中,则计数更改为22.如果我从子查询中取出AND SGBSTDN_PIDM = SFRSTCR_PIDM,则计数也会更改为22.有人可以向我解释这个吗? / p>

3 个答案:

答案 0 :(得分:6)

您有一个相关的子查询。这与非相关子查询略有不同,因为它可以包含对外部表的引用。

使用相关子查询时,始终对所有表引用使用表别名。一般来说这是个好主意,但应该更加注意相关的子查询。

AND SGBSTDN_TERM_CODE_EFF = (SELECT MAX(SGBSTDN.SGBSTDN_TERM_CODE_EFF)
                             FROM SATURN.SGBSTDN
                             WHERE SGBSTDN.SGBSTDN_TERM_CODE_EFF <=  '200002'
                               AND SGBSTDN.SGBSTDN_PIDM = SFRSTCR.SFRSTCR_PIDM
                            )

对于SFRSTCR.SFRSTCR_PIDM的每个值(以及其他条件),子查询将获得最大日期。

在大多数SQL版本中,fromwherehaving子句中允许使用相关子查询。 (他们也可能被允许进入order by。)

答案 1 :(得分:2)

Correlated subqueries(即WHERE子句中的子查询)可以引用外部查询中的列。它们与内联视图(即FROM子句中的子查询)不同,无法查看父查询中定义的列。

您正在做得正确:子查询将首先在其范围(SFRSTCR_PIDM)中查找SATURN.SGBSTDN列,然后在外部查询中查找它。

答案 2 :(得分:0)

您列出的子查询将获取正在处理的外层级别的当前记录,并使AVAILABLE成为子查询,这就是您不明确需要将其包含在子查询中的原因。如果列是唯一可识别的,则不需要alias.column引用,只能使用columnName引用。

但是,子查询的性能通常很差,因为子查询是针对每个正在处理的记录运行的。通常使用连接,但每个查询都有自己的需求,并且您在子查询级别获得MAX()。