Oracle SQL引用外部表字段在派生表中嵌套查询

时间:2017-10-09 22:45:58

标签: sql oracle oracle11g

我需要在派生表中引用外部查询中的字段。问题是我需要使用外部表中的值(在本例中为A)限制从派生表中获取的最大日期,因为外部表是一个临时工作表,由进程填充特定值。

以下方法不正确,因为它无法正确引用外部表。有没有更好的方法来写这个?

下面是我希望它如何工作的示例:

    SELECT A.EMP, X.SCHEDULE, A.DATE FROM CUST A, (SELECT T1.EMP, T1.NAME, CASE WHEN T1.USER1 = '3' THEN T2.USER4 ELSE T1.USER4 END AS Schedule 
                           FROM TEMP1 T1, TEMP2 T2, TEMP3 T3
                           WHERE T1.EMP = T3.EMP
                           AND T2.VALUE= T3.VALUE
                           AND T1.DATE = (SELECT MAX(T1A.DATE) FROM TEMP1 T1A
                                          WHERE T1A.EMP = T1.EMP
                                          AND T1A.DATE <= A.DATE)
                           AND T2.DATE = (SELECT MAX(T2A.DATE) FROM TEMP2 T2A
                                          WHERE T2A.VALUE= T2.VALUE
                                          AND T2A.DATE <= A.DATE)
                           AND T3.DATE = (SELECT MAX(T3A.DATE) FROM TEMP3 T3A
                                          WHERE T3A.EMP = T3.EMP
                                          AND T3A.VALUE = T3.VALUE
                                          AND T3A.DATE <= A.DATE)) X
    WHERE A.EMP = X.EMP
    AND X.EMP IN ('1','2');

以下是一些示例数据和结果:

TABLE CUST
EMP     DATE     VALUE
1       1/1/17   R
2       2/1/17   R

TABLE TEMP1
EMP     DATE     USER1     USER4     
1       3/2/16   3         4
1       5/1/17   3         3
2       2/1/17   9         2


TABLE TEMP2 
DATE     VALUE     USER4  
1/1/01   S         100   
1/1/03   P         200
1/3/07   R         300
8/1/17   R         350

TABLE TEMP3
EMP     DATE     VALUE     
1       3/2/16   R
1       5/1/17   R
2       2/1/17   R

示例输出应为:

EMP     SCHEDULE     DATE
1       300          1/1/17
2       2            2/1/17    

2 个答案:

答案 0 :(得分:0)

As&#34; date&#34;是一个SQL保留字(对于Oracle中的数据类型)我绝不会将其用作列名。下面我使用了DATECOL。

我认为通过一组简单的连接比较日期要容易得多。

查看此工作here at SQL Fiddle

SELECT
      T1.EMP
      --, T1.NAME
    , CASE WHEN T1.USER1 = '3'
                  THEN
                        T2.USER4 ELSE
                  T1.USER4
      END        AS Schedule
    , c.datecol
    , t1.datecol t1date
    , t2.datecol t2date
    , t3.datecol t3date
FROM TEMP1 T1
INNER JOIN cust c ON T1.EMP = c.EMP
INNER JOIN TEMP3 T3 ON T1.EMP = T3.EMP
INNER JOIN TEMP2 T2 ON T3.VALUE = T2.VALUE
WHERE t1.datecol <= c.datecol
AND t2.datecol <= c.datecol
AND t3.datecol <= c.datecol

查询1

| EMP | SCHEDULE |              DATECOL |               T1DATE |               T2DATE |               T3DATE |
|-----|----------|----------------------|----------------------|----------------------|----------------------|
|   1 |      300 | 2017-01-01T00:00:00Z | 2016-03-02T00:00:00Z | 2007-01-03T00:00:00Z | 2016-03-02T00:00:00Z |
|   2 |        2 | 2017-02-01T00:00:00Z | 2017-02-01T00:00:00Z | 2007-01-03T00:00:00Z | 2017-02-01T00:00:00Z |

<强> Results

{{1}}

同样,超过25年前,SQL标准化了一种更好的方法将表连接在一起。要记住的这个简单技巧是停止在FROM子句中使用表名之间的逗号。这有助于确保采用显式连接语法。

答案 1 :(得分:0)

我尝试了你的样本数据,我得到了输出。我已经重写了你的查询并得到了预期的输出。

SELECT A.emp, A.tdate,
       CASE WHEN T1.USER1 = '3' THEN T2.USER4 ELSE T1.USER4 END AS Schedule
  FROM CUST A, Temp1 t1, temp2 t2, temp3 t3
 WHERE A.emp=t1.emp
   AND A.tvalue = t2.tvalue
   AND A.emp = t3.emp
   AND A.tvalue = t3.tvalue
   AND t1.tdate <=(SELECT max(tdate) from temp1 t where tdate<=A.tdate and t.emp=A.emp)
   AND t2.tdate <= (SELECT max(tdate) from temp2 t where tdate <= A.tdate and A.tvalue = t.tvalue)
   AND t3.tdate <=(SELECT max(tdate) from temp3 t where tdate <= A.tdate and A.tvalue = t.tvalue and t.emp=A.emp)

如果临时表中只有一个日期小于cust表中的日期,则使用以下查询

SELECT A.emp, A.tdate,
       CASE WHEN T1.USER1 = '3' THEN T2.USER4 ELSE T1.USER4 END AS Schedule
  FROM CUST A, Temp1 t1, temp2 t2, temp3 t3
 WHERE A.emp=t1.emp
   AND A.tvalue = t2.tvalue
   AND A.emp = t3.emp
   AND A.tvalue = t3.tvalue
   AND t1.tdate <=A.tdate
   AND t2.tdate <= A.tdate
   AND t3.tdate <= A.tdate

注意: - 日期和值等列名称会在创建表时抛出错误。它们是保留关键字