我试图使这个查询的一部分成为有条件的,但我真的很难做到这一点。下面我输入了一些代表我的查询的伪代码。
主要查询
SELECT A.T_NBR
,A.I_NBR
,A.DATE
,A.MX_CD
,A.MY_CD
,A.S_CD
,B.O_NBR
FROM A,B,C,D,E,F,H,I,TMP_J
WHERE A.MY_CD IN ('FOO','BAR')
AND A.T_NBR NOT IN (
SELECT A.T_NBR
FROM A,K
WHERE A.MY_CD = 'BAR'
AND P_DATE < ADD_MONTHS(SYSDATE, -36)
AND A.S_CD NOT IN ('AAA','BBB')
AND K.K_CD NOT IN ('DDD','EEE')
--JOIN
AND A.I_NBR = K.I_NBR(+)
)
AND U_CD = 'FFFF'
--DATE LESS THAN 3 YEARS
AND TO_DATE(H.DATE,'YYYY-MM-DD') < ADD_MONTHS(SYSDATE, -36)
--NUM GREATER THAN 23
AND TO_CHAR(SYSDATE,'SYYYY')-TO_CHAR(I.NUM,'SYYYY') > 23
AND A.S_CD NOT IN ('AAA','BBB')
AND B.DATE = (
SELECT MAX(DATE)
FROM B
)
AND B.O_NBR < 200
AND F.MG_CD <> '000'
AND A.T_NBR NOT IN (12345,54321,98765)
AND ((E.T IS NULL) OR (RTRIM(E.T) LIKE '%###%'))
AND TMP_J.I_NBR IS NULL
--JOINS
AND A.T_BR = B.T_NBR(+)
AND ((B.I_NBR = F.I_NBR) AND (B.DATE = F.DATE))
AND A.S_NBR = D.S_NBR(+)
AND A.D_NBR = C.D_NBR(+)
AND ((D.S_NBR = G.S_NBR(+)) AND (UPPER(G.A_CD(+)) = 'XXX'))
AND G.A_NBR = E.A_NBR(+)
AND H.I_NBR = A.I_NBR
AND A.S_NBR = I.S_NBR(+)
AND A.T_NBR = TMP_J.T_NBR(+);
本质上,这就是我想要做的条件(用简单的英语和伪代码写出来):
如果
A.MY_CD = 'BAR'
然后
A.T_NBR NOT IN (
SELECT A.T_NBR
FROM A,K
WHERE A.MY_CD = 'BAR'
AND P_DATE < ADD_MONTHS(SYSDATE, -36)
AND A.S_CD NOT IN ('AAA','BBB')
AND K.K_CD NOT IN ('DDD','EEE')
--JOIN
AND A.I_NBR = K.I_NBR(+)
)
否则如果
A.MY_CD = 'FOO'
然后
WHERE U_CD = 'FFFF'
--DATE LESS THAN 3 YEARS
AND TO_DATE(H.DATE,'YYYY-MM-DD') < ADD_MONTHS(SYSDATE, -36)
--NUM GREATER THAN 23
AND TO_CHAR(SYSDATE,'SYYYY')-TO_CHAR(I.NUM,'SYYYY') > 23
然后我只想其余的 where 子句在 Condition 之外进行操作。
除了不知道哪种方法最有效(CASE/WHEN、DECODE、IF/THEN)之外,我真正遇到困难的部分是尝试在这些条件子句中实现 SELECT 语句。我尝试在查询的 SELECT 和 WHERE 部分中实现 CASE WHEN,同时尝试将 SELECT 语句放在 CASE 语句的 WHEN 部分中。我也以同样的方式尝试过解码。此外,我尝试实现 IF/THEN,但似乎无法将其与我的主查询联系起来。
对于 PL/SQL,我当然不是专业人士,所以这可能只是我的知识失误。使该查询的一部分成为条件的最佳方法是什么?
非常感谢您的回复和帮助!
您似乎只想将条件与 AND/OR 逻辑结合起来;无需对您的方法进行任何其他更改:
...
FROM A,B,C,D,E,F,H,I,TMP_J
WHERE
(
(
A.MY_CD = 'BAR'
AND A.T_NBR NOT IN (
SELECT A.T_NBR
FROM A,K
WHERE A.MY_CD = 'BAR'
AND P_DATE < ADD_MONTHS(SYSDATE, -36)
AND A.S_CD NOT IN ('AAA','BBB')
AND K.K_CD NOT IN ('DDD','EEE')
--JOIN
AND A.I_NBR = K.I_NBR(+)
)
)
OR
(
A.MY_CD = 'FOO'
AND U_CD = 'FFFF'
--DATE LESS THAN 3 YEARS
AND TO_DATE(H.DATE,'YYYY-MM-DD') < ADD_MONTHS(SYSDATE, -36)
--NUM GREATER THAN 23
AND TO_CHAR(SYSDATE,'SYYYY')-TO_CHAR(I.NUM,'SYYYY') > 23
)
)
AND A.S_CD NOT IN ('AAA','BBB')
AND B.DATE = (
SELECT MAX(DATE)
FROM B
)
AND B.O_NBR < 200
AND F.MG_CD <> '000'
AND A.T_NBR NOT IN (12345,54321,98765)
AND ((E.T IS NULL) OR (RTRIM(E.T) LIKE '%###%'))
AND TMP_J.I_NBR IS NULL
--JOINS
...
从逻辑上讲,这似乎就是您所要求的。但您需要查看执行计划和性能等。还有各种其他问题需要考虑,包括切换到使用显式连接,
not in
vs not exists
(如评论中所述),不将日期存储为字符串,也许使用(更多,现代)连接而不是子查询,也许使用extract()
获取您的年份数字而不是 to_char()
并隐式转换为数字(如果该子句有意义),等等。
这是我的想法:
IF A = X
THEN
IF B = Y
CASE 1
ELSE
CASE 2
ELSE
IF C = Z
CASE 3
可以重写为
IF (A = X) AND (B = Y)
CASE 1
IF (A = X) AND (B != Y)
CASE 2
IF (A != X) AND (C = Z)
CASE 3
可以将其翻译成如下 SQL WHERE 语句:
WHERE
-- Case 1
((A = X) AND (B = Y)) -- you can put more clauses here with AND statements
OR
-- Case 2
((A = X) AND (B != Y)) -- you can put more clauses here with AND statements
OR
-- Case 3
((A != X) AND (C = Z)) -- you can put more clauses here with AND statements