派生表中的Oracle SQL引用外部表字段嵌套查询
问题描述:
我需要从派生表中的外部查询引用一个字段。问题是我需要使用外部表中的值(本例中为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
答
我试着用你的示例数据,我得到了输出。我已经重写了您的查询并获得了预期的输出结果。
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
注: - 如日期和值的列名在创建表时会引发错误。他们是保留的关键字
答
由于“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
| 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子句中的表名之间停止使用逗号。这有助于确保显式连接语法被采用。
你能用例子来解释吗?预期的和实际的输出将使它看起来更好 – Valli
对他人理解的绝望的查询。我建议你学习正确的,明确的'JOIN'语法。您也可以解释查询应该做什么,提供样本数据和期望的结果。可能有一个更简单的方法。 –
@valli我已经添加了一些测试场景 – Help123