在 Oracle SQL 中未获得预期结果
Not getting expected results in Oracle SQL
我有一个带有 5 个提示的查询
:1 - EMPLID
:2 - APPL_NBR
:3 - CHECKLIST_CD
:4 - CHECKLIST STATUS
:5 - ADMIT_TERM
我的查询的问题是它不遵循下面给出的标准的结果:
- 没有强制性提示,因此如果报告 运行 所有条件均为空白,则会发生以下情况:
- 无论何时创建,都会显示所有未完成/正在处理清单的学生。
- 将显示在当前学期内完成核对清单的所有学生。
- 如果指定了(过去的)录取期限,e-i 中的案例将显示指定期限的完整清单。
- 如果指定了(过去的)录取期限,则只会显示在该期限内创建但仍未完成/正在进行的清单的清单。
- 如果指定了未来的录取期限,则只会显示当前未完成/进行中的清单。
这里是 sql:
SELECT A.EMPLID, A.NAME, A.ADM_APPL_NBR, A.ADMIN_FUNCTION, A.STDNT_CAR_NBR,
A.ACAD_CAREER, A.APPL_PROG_NBR, A.ADMIT_TERM, A.CHECKLIST_CD, A.DESCRSHORT,
A.CHECKLIST_STATUS, TO_CHAR(A.STATUS_DT,'YYYY-MM-DD'),
TO_CHAR(A.DUE_DT,'YYYY-MM-DD'), A.COMM_COMMENTS, A.SEQ_3C, A.CHKLST_ITEM_CD,
A.DESCR, A.ITEM_STATUS, TO_CHAR(A.UM_STATUS_DT_CL,'YYYY-MM-DD'),
TO_CHAR(A.UM_DUE_DT_CL,'YYYY-MM-DD'), A.RESPONSIBLE_ID
FROM PS_UM_7902_VW2 A
--for Condition 1, for prompts with no values provided
WHERE ( 1 = 1 AND EMPLID LIKE DECODE (:1, '', '%', :1)
AND ADM_APPL_NBR LIKE DECODE(:2, '', '%', :2)
AND CHECKLIST_CD LIKE DECODE(:3, '', '%', :3)
AND A.CHECKLIST_STATUS = :4
OR '' = :4
AND A.CHECKLIST_STATUS = 'I'
OR ( A.CHECKLIST_STATUS = 'C'
AND SYSDATE BETWEEN A.TERM_BEGIN_DT AND A.TERM_END_DT)
AND ( A.ADMIT_TERM = A.STRM
AND SYSDATE BETWEEN A.TERM_BEGIN_DT AND A.TERM_END_DT)
-- end for Condition 1
OR A.EMPLID = :1
AND ( 1 = 1 AND ADM_APPL_NBR LIKE DECODE(:2, '', '%', :2)
AND CHECKLIST_CD LIKE DECODE(:3, '', '%', :3)
AND A.CHECKLIST_STATUS = 'I'
OR ( A.CHECKLIST_STATUS = 'C'
AND SYSDATE BETWEEN A.TERM_BEGIN_DT AND A.TERM_END_DT)
AND ( A.ADMIT_TERM = A.STRM
AND SYSDATE BETWEEN A.TERM_BEGIN_DT AND A.TERM_END_DT))
OR A.ADM_APPL_NBR = :2
AND ( 1 = 1 AND EMPLID LIKE DECODE (:1, '', '%', :1)
AND CHECKLIST_CD LIKE DECODE(:3, '', '%', :3)
AND A.CHECKLIST_STATUS = 'I'
OR ( A.CHECKLIST_STATUS = 'C'
AND SYSDATE BETWEEN A.TERM_BEGIN_DT AND A.TERM_END_DT)
AND ( A.ADMIT_TERM = A.STRM
AND SYSDATE BETWEEN A.TERM_BEGIN_DT AND A.TERM_END_DT))
OR A.CHECKLIST_CD = :3
AND ( 1 = 1 AND EMPLID LIKE DECODE (:1, '', '%', :1)
AND ADM_APPL_NBR LIKE DECODE(:2, '', '%', :2)
AND A.CHECKLIST_STATUS = 'I'
OR ( A.CHECKLIST_STATUS = 'C'
AND SYSDATE BETWEEN A.TERM_BEGIN_DT AND A.TERM_END_DT)
AND ( A.ADMIT_TERM = A.STRM
AND SYSDATE BETWEEN A.TERM_BEGIN_DT AND A.TERM_END_DT))
OR A.CHECKLIST_STATUS = :4
AND ( 1 = 1 AND EMPLID LIKE DECODE (:1, '', '%', :1)
AND ADM_APPL_NBR LIKE DECODE(:2, '', '%', :2)
AND CHECKLIST_CD LIKE DECODE(:3, '', '%', :3))
OR ( A.CHECKLIST_STATUS = 'C'
AND SYSDATE BETWEEN A.TERM_BEGIN_DT AND A.TERM_END_DT)
AND ( A.ADMIT_TERM = A.STRM
AND SYSDATE BETWEEN A.TERM_BEGIN_DT AND A.TERM_END_DT)
--for Conditions 2, 3 and 4 for ADMIT_TERM
OR A.ADMIT_TERM = :5
AND 1 = 1 AND EMPLID LIKE DECODE (:1, '', '%', :1)
AND ADM_APPL_NBR LIKE DECODE(:2, '', '%', :2)
AND CHECKLIST_CD LIKE DECODE(:3, '', '%', :3)
AND (( SYSDATE > A.TERM_END_DT
AND A.CHECKLIST_STATUS = 'C')
OR SYSDATE BETWEEN A.TERM_BEGIN_DT AND A.TERM_END_DT)
AND ( A.CHECKLIST_STATUS = 'I'
OR ( SYSDATE < A.TERM_BEGIN_DT
AND A.CHECKLIST_STATUS = 'I')));
-- end for Conditions 2, 3 and 4
我已经隔离了我执行条件 1、2、3 和 4 的部分。中间的大部分部分在给定条件下都可以正常工作。我做错了什么吗?特别是在第一部分,我认为应该很容易将该提示的所有值提取为默认值。
感谢我能得到的所有帮助。
谢谢!
我认为您的主要问题在于使用 ''
来表示 null
。我建议不要这样做,因为其他语言对待空字符串的方式与 SQL 非常不同。
所以首先,decode
这些天不受欢迎,原因有几个。而不是例如
EMPLID LIKE DECODE (:1, '', '%', :1)
我愿意
EMPLID LIKE NVL(:1, '%')
其次,这可能是给您带来麻烦的部分,这些行没有按照您的要求进行:
AND A.CHECKLIST_STATUS = :4
OR '' = :4
第二行永远不会是真的。任何与 null 的比较都将为 null,而不是 true。所以 '' = ''
将 return 为空,不正确。为了清楚起见,通常认为将括号与 AND/OR 混合使用是一种很好的做法。所以相反,我会做这样的事情:
AND (A.CHECKLIST_STATUS = :4 OR :4 is null)
我有一个带有 5 个提示的查询
:1 - EMPLID
:2 - APPL_NBR
:3 - CHECKLIST_CD
:4 - CHECKLIST STATUS
:5 - ADMIT_TERM
我的查询的问题是它不遵循下面给出的标准的结果:
- 没有强制性提示,因此如果报告 运行 所有条件均为空白,则会发生以下情况:
- 无论何时创建,都会显示所有未完成/正在处理清单的学生。
- 将显示在当前学期内完成核对清单的所有学生。
- 如果指定了(过去的)录取期限,e-i 中的案例将显示指定期限的完整清单。
- 如果指定了(过去的)录取期限,则只会显示在该期限内创建但仍未完成/正在进行的清单的清单。
- 如果指定了未来的录取期限,则只会显示当前未完成/进行中的清单。
这里是 sql:
SELECT A.EMPLID, A.NAME, A.ADM_APPL_NBR, A.ADMIN_FUNCTION, A.STDNT_CAR_NBR,
A.ACAD_CAREER, A.APPL_PROG_NBR, A.ADMIT_TERM, A.CHECKLIST_CD, A.DESCRSHORT,
A.CHECKLIST_STATUS, TO_CHAR(A.STATUS_DT,'YYYY-MM-DD'),
TO_CHAR(A.DUE_DT,'YYYY-MM-DD'), A.COMM_COMMENTS, A.SEQ_3C, A.CHKLST_ITEM_CD,
A.DESCR, A.ITEM_STATUS, TO_CHAR(A.UM_STATUS_DT_CL,'YYYY-MM-DD'),
TO_CHAR(A.UM_DUE_DT_CL,'YYYY-MM-DD'), A.RESPONSIBLE_ID
FROM PS_UM_7902_VW2 A
--for Condition 1, for prompts with no values provided
WHERE ( 1 = 1 AND EMPLID LIKE DECODE (:1, '', '%', :1)
AND ADM_APPL_NBR LIKE DECODE(:2, '', '%', :2)
AND CHECKLIST_CD LIKE DECODE(:3, '', '%', :3)
AND A.CHECKLIST_STATUS = :4
OR '' = :4
AND A.CHECKLIST_STATUS = 'I'
OR ( A.CHECKLIST_STATUS = 'C'
AND SYSDATE BETWEEN A.TERM_BEGIN_DT AND A.TERM_END_DT)
AND ( A.ADMIT_TERM = A.STRM
AND SYSDATE BETWEEN A.TERM_BEGIN_DT AND A.TERM_END_DT)
-- end for Condition 1
OR A.EMPLID = :1
AND ( 1 = 1 AND ADM_APPL_NBR LIKE DECODE(:2, '', '%', :2)
AND CHECKLIST_CD LIKE DECODE(:3, '', '%', :3)
AND A.CHECKLIST_STATUS = 'I'
OR ( A.CHECKLIST_STATUS = 'C'
AND SYSDATE BETWEEN A.TERM_BEGIN_DT AND A.TERM_END_DT)
AND ( A.ADMIT_TERM = A.STRM
AND SYSDATE BETWEEN A.TERM_BEGIN_DT AND A.TERM_END_DT))
OR A.ADM_APPL_NBR = :2
AND ( 1 = 1 AND EMPLID LIKE DECODE (:1, '', '%', :1)
AND CHECKLIST_CD LIKE DECODE(:3, '', '%', :3)
AND A.CHECKLIST_STATUS = 'I'
OR ( A.CHECKLIST_STATUS = 'C'
AND SYSDATE BETWEEN A.TERM_BEGIN_DT AND A.TERM_END_DT)
AND ( A.ADMIT_TERM = A.STRM
AND SYSDATE BETWEEN A.TERM_BEGIN_DT AND A.TERM_END_DT))
OR A.CHECKLIST_CD = :3
AND ( 1 = 1 AND EMPLID LIKE DECODE (:1, '', '%', :1)
AND ADM_APPL_NBR LIKE DECODE(:2, '', '%', :2)
AND A.CHECKLIST_STATUS = 'I'
OR ( A.CHECKLIST_STATUS = 'C'
AND SYSDATE BETWEEN A.TERM_BEGIN_DT AND A.TERM_END_DT)
AND ( A.ADMIT_TERM = A.STRM
AND SYSDATE BETWEEN A.TERM_BEGIN_DT AND A.TERM_END_DT))
OR A.CHECKLIST_STATUS = :4
AND ( 1 = 1 AND EMPLID LIKE DECODE (:1, '', '%', :1)
AND ADM_APPL_NBR LIKE DECODE(:2, '', '%', :2)
AND CHECKLIST_CD LIKE DECODE(:3, '', '%', :3))
OR ( A.CHECKLIST_STATUS = 'C'
AND SYSDATE BETWEEN A.TERM_BEGIN_DT AND A.TERM_END_DT)
AND ( A.ADMIT_TERM = A.STRM
AND SYSDATE BETWEEN A.TERM_BEGIN_DT AND A.TERM_END_DT)
--for Conditions 2, 3 and 4 for ADMIT_TERM
OR A.ADMIT_TERM = :5
AND 1 = 1 AND EMPLID LIKE DECODE (:1, '', '%', :1)
AND ADM_APPL_NBR LIKE DECODE(:2, '', '%', :2)
AND CHECKLIST_CD LIKE DECODE(:3, '', '%', :3)
AND (( SYSDATE > A.TERM_END_DT
AND A.CHECKLIST_STATUS = 'C')
OR SYSDATE BETWEEN A.TERM_BEGIN_DT AND A.TERM_END_DT)
AND ( A.CHECKLIST_STATUS = 'I'
OR ( SYSDATE < A.TERM_BEGIN_DT
AND A.CHECKLIST_STATUS = 'I')));
-- end for Conditions 2, 3 and 4
我已经隔离了我执行条件 1、2、3 和 4 的部分。中间的大部分部分在给定条件下都可以正常工作。我做错了什么吗?特别是在第一部分,我认为应该很容易将该提示的所有值提取为默认值。
感谢我能得到的所有帮助。
谢谢!
我认为您的主要问题在于使用 ''
来表示 null
。我建议不要这样做,因为其他语言对待空字符串的方式与 SQL 非常不同。
所以首先,decode
这些天不受欢迎,原因有几个。而不是例如
EMPLID LIKE DECODE (:1, '', '%', :1)
我愿意
EMPLID LIKE NVL(:1, '%')
其次,这可能是给您带来麻烦的部分,这些行没有按照您的要求进行:
AND A.CHECKLIST_STATUS = :4
OR '' = :4
第二行永远不会是真的。任何与 null 的比较都将为 null,而不是 true。所以 '' = ''
将 return 为空,不正确。为了清楚起见,通常认为将括号与 AND/OR 混合使用是一种很好的做法。所以相反,我会做这样的事情:
AND (A.CHECKLIST_STATUS = :4 OR :4 is null)