0

我需要在以下 SQL 中正常工作的表中选择名字和姓氏,但不工作的部分是 NVL 函数。该文件应显示飞行直升机公司的所有飞行员,如果他们没有执照,则字段 HT_NAME 应显示为“N/A”,飞行结束时间字段应为 0。我已将 NVL 功能作为我的文本详细信息,但它仍然无法正常工作。我犯了语法错误吗?帮助将不胜感激。

Select E.EMP_NBR, E.EMP_FIRSTNAME || ' ' || E.EMP_LASTNAME, E.EMP_PILOT,
       ED.HT_NBR, NVL(HT.HT_NAME, 'N/A'), NVL(ED.END_HRS_FLOWN, 0),
       ED.END_LAST_ANNUAL_REVIEW_DATE
From  ENDORSEMENT ED, EMPLOYEE E, HELICOPTER_TYPE HT
WHERE HT.HT_NBR = ED.HT_NBR (+)
ORDER BY ED.END_HRS_FLOWN DESC, E.EMP_FIRSTNAME || ' ' || E.EMP_LASTNAME ASC;

应该使非飞行员的员工在直升机类型下显示为 N/A,在飞行小时数下显示为 0。它不起作用 - 即使我尝试了多种方法来修复它。

4

3 回答 3

1

You have three tables and only one join condition; you need a join between Employee and Endorsement. Without that, you are getting a cross-product or Cartesian join between those tables.

With N tables (N > 0), you need J = N-1 join conditions at minimum. You have N = 3 tables, but J = 1 join conditions - which is too few. (There are various reasons why you might need J > N - 1, but the main one is because you need to join two columns between two tables. If you count each 'A.Col1 = B.Col2' condition as a separate join condition, then you need J > N-1; if you count the pair of conditions 'A.Col1 = B.Col2 AND A.Col3 = B.Col4' as a single join condition, then you still only need J = N-1 conditions. )

Ideally, you should also move away from the archaic, non-standard outer join notation using '(+)' and use the standard SQL joins.


The notation is a secondary issue. Every row in Employee is being joined with every row in Endorsement - and then that cross-product is being outer-joined with Helicopter_type. This is (almost certainly) not the query that is required.

You probably need to add some variation of this to the WHERE clause:

AND E.EMP_NBR = ED.EMP_NBR

(where the actual column in the Endorsement (ED) table is not shown in the query, so 'ED.EMP_NBR' is a guess).

Amongst other effects, if there are any helicopter pilots in the database, then every employee record is being joined with the endorsement for a pilot some of the time, and the sort order means that those records will be shown before the myriad records which show that the pilots don't have helicopter endorsements and that non-pilots don't have helicopter records, etc...

于 2010-06-10T08:14:19.663 回答
1

正如@Jonathan 所说,您需要在 WHERE 子句中添加一些内容来告诉数据库如何将 EMPLOYEE 与 ENDORSEMENT 匹配。出于讨论的目的,我们将在两者上使用 EMP_NBR 字段,但您需要更改查询以使用正确的字段。我们还需要知道员工是否拥有有效许可证的字段会告诉您。我猜它是 ENDORSEMENT 表上的东西——为了讨论的目的,我们称它为 ENDORSEMENT.LICENSE_TYPE。一旦知道可以使用 NVL2 函数适当地更改查询返回的值,如下所示:

SELECT E.EMP_NBR,
       E.EMP_FIRSTNAME || ' ' || E.EMP_LASTNAME AS FIRST_LAST_NAME,
       E.EMP_PILOT, 
       ED.HT_NBR,
       NVL2(ED.LICENSE_TYPE, HT.HT_NAME, 'N/A') HELO_TYPE,
       NVL2(ED.LICENSE_TYPE, ED.END_HRS_FLOWN, 0) FLOWN_HOURS, 
       ED.END_LAST_ANNUAL_REVIEW_DATE 
  FROM ENDORSEMENT ED,
       EMPLOYEE E,
       HELICOPTER_TYPE HT 
  WHERE HT.HT_NBR = ED.HT_NBR (+) AND
        ED.EMP_NBR = E.EMP_NBR (+)
  ORDER BY ED.END_HRS_FLOWN DESC,
           E.EMP_LASTNAME ASC,
           E.EMP_FIRSTNAME ASC;

我还更改了 ORDER BY 子句,以更正常的方式对员工进行排序。

分享和享受。

于 2010-06-10T11:32:26.680 回答
0

检查 HT_NAME 和 END_HRS_FLOWN 对于您期望 N/A 或 0 的行是否具有空值

编辑 1

在 Oracle 中,NVL 函数允许您在遇到空值时替换一个值。

NVL 函数的语法是:

NVL( string1, replace_with )

string1是要测试空值的字符串。

如果 string1 为空,则replace_with是返回的值。

如果值不是 null,它将返回相同的值

于 2010-06-10T08:28:50.817 回答