2017-10-09 115 views
0

我需要從派生表中的外部查詢引用一個字段。問題是我需要使用外部表中的值(本例中爲A)限制從派生表中獲取的最大日期,因爲外部表是一個臨時工作表,它由進程填充了特定值。派生表中的Oracle SQL引用外部表字段嵌套查詢

下面的方法是不正確的,因爲它無法正確引用外部表。有沒有更好的方法來寫這個?

下面是我怎麼想它的工作的例子:

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 

樣本輸出應該是::

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'); 

下面是一些示例數據和結果

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

你能用例子來解釋嗎?預期的和實際的輸出將使它看起來更好 – Valli

+0

對他人理解的絕望的查詢。我建議你學習正確的,明確的'JOIN'語法。您也可以解釋查詢應該做什麼,提供樣本數據和期望的結果。可能有一個更簡單的方法。 –

+0

@valli我已經添加了一些測試場景 – Help123

回答

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) 

如果你將不得不在臨時表只有一個日期是小於卡斯特表的日期,然後用下面的查詢

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 

注: - 如日期和值的列名在創建表時會引發錯誤。他們是保留的關鍵字

0

由於「date」是一個SQL保留字(對於Oracle中的數據類型),我絕不會將它用作列名。下面我用DATECOL來代替。

我認爲通過一組簡單的連接比較日期要容易得多。

看到這個工作here at SQL Fiddle

CREATE TABLE CUST 
    (EMP int, DATECOL date, VALUE varchar2(1)) 
; 

INSERT ALL 
    INTO CUST (EMP, DATECOL, VALUE) 
     VALUES (1, to_date('01-Jan-2017','dd-mon-yyyy'), 'R') 
    INTO CUST (EMP, DATECOL, VALUE) 
     VALUES (2, to_date('01-Feb-2017','dd-mon-yyyy'), 'R') 
SELECT * FROM dual 
; 

CREATE TABLE TEMP1 
    (EMP int, DATECOL date, USER1 int, USER4 int) 
; 

INSERT ALL 
    INTO TEMP1 (EMP, DATECOL, USER1, USER4) 
     VALUES (1, to_date('02-Mar-2016','dd-mon-yyyy'), 3, 4) 
    INTO TEMP1 (EMP, DATECOL, USER1, USER4) 
     VALUES (1, to_date('01-May-2017','dd-mon-yyyy'), 3, 3) 
    INTO TEMP1 (EMP, DATECOL, USER1, USER4) 
     VALUES (2, to_date('01-Feb-2017','dd-mon-yyyy'), 9, 2) 
SELECT * FROM dual 
; 

CREATE TABLE TEMP2 
    (DATECOL date, VALUE varchar2(1), USER4 int) 
; 

INSERT ALL 
    INTO TEMP2 (DATECOL, VALUE, USER4) 
     VALUES (to_date('01-Jan-2001','dd-mon-yyyy'), 'S', 100) 
    INTO TEMP2 (DATECOL, VALUE, USER4) 
     VALUES (to_date('01-Jan-2003','dd-mon-yyyy'), 'P', 200) 
    INTO TEMP2 (DATECOL, VALUE, USER4) 
     VALUES (to_date('03-Jan-2007','dd-mon-yyyy'), 'R', 300) 
    INTO TEMP2 (DATECOL, VALUE, USER4) 
     VALUES (to_date('01-Aug-2017','dd-mon-yyyy'), 'R', 350) 
SELECT * FROM dual 
; 

CREATE TABLE TEMP3 
    (EMP int, DATECOL date, VALUE varchar2(1)) 
; 

INSERT ALL 
    INTO TEMP3 (EMP, DATECOL, VALUE) 
     VALUES (1, to_date('02-Mar-2016','dd-mon-yyyy'), 'R') 
    INTO TEMP3 (EMP, DATECOL, VALUE) 
     VALUES (1, to_date('01-May-2017','dd-mon-yyyy'), 'R') 
    INTO TEMP3 (EMP, DATECOL, VALUE) 
     VALUES (2, to_date('01-Feb-2017','dd-mon-yyyy'), 'R') 
SELECT * FROM dual 
; 

查詢1

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 

Results

| 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 | 

也是,超過25年前SQL通過更好的方法將表連接在一起進行了標準化。這個簡單的技巧要記住的是在FROM子句中的表名之間停止使用逗號。這有助於確保顯式連接語法被採用。