如何在WHERE子句中用CASE WHEN实现全量/增量动态查询?
如何修改Oracle SQL的CASE WHEN实现动态过滤逻辑?
我需要实现一个动态过滤的Oracle SQL查询:
- 当参数
:attribute为'Full Run'时,不添加额外过滤条件,返回全量结果 - 当参数
:attribute为'Changed Attributes'时,仅返回max_update_date大于等于另一表中最大处理日期的记录
现有查询的CASE WHEN写法无法实现该逻辑,原查询如下:
select * from (SELECT DISTINCT fs.set_code, GRADE_LAD.NAME GRADE_LADDER, To_char(GRADE_LAD.effective_start_date, 'yyyy/mm/dd') GRADE_LAD_START_DATE, GRADE_LAD.active_status, GRADE_LAD.attribute1 SAL_PLAN_DESCR, GRADE_LAD.attribute2 SHORT_DESCR, Max(GRADE_LAD.last_update_date) OVER( partition BY GRADE_LAD.grade_ladder_id) max_update_date FROM fnd_setid_assignments fsa, fnd_setid_sets_vl fs, per_grade_ladders_f_vl GRADE_LAD, fun_all_business_units_v bu WHERE 1 = 1 AND fsa.determinant_value = bu.bu_id AND fsa.determinant_type = 'BU' AND fsa.set_id = fs.set_id AND FS.set_id = grade_set_id AND fsa.reference_group_name LIKE 'PER_GRADES' AND :EffectiveDate BETWEEN GRADE_LAD.effective_start_date AND GRADE_LAD.effective_end_date --AND GRADE_LAD.NAME LIKE '%Test%' ) where case when (:attribute = 'Full Run') then 1 when (:attribute='Changed Attribute') then 1 else 0 end = 1
当参数为'Changed Attributes'时,需要满足的过滤条件是:
max_update_date >= Nvl( (SELECT Max(processstart) FROM fusion.ess_request_history erh, fusion.ess_request_property erp WHERE erh.requestid = erp.requestid AND state = 12 AND erp.NAME = 'reportID' AND erp.value LIKE '/Custom/Integrations/Extract.xdo' ),max_update_date)
请问该如何修改CASE WHEN语句实现上述需求?
解决方案
不需要用CASE WHEN封装整个条件,直接用OR分支处理两种参数场景更清晰高效:
select * from (SELECT DISTINCT fs.set_code, GRADE_LAD.NAME AS GRADE_LADDER, -- 补全列别名,修复原语法问题 To_char(GRADE_LAD.effective_start_date, 'yyyy/mm/dd') AS GRADE_LAD_START_DATE, GRADE_LAD.active_status, GRADE_LAD.attribute1 AS SAL_PLAN_DESCR, GRADE_LAD.attribute2 AS SHORT_DESCR, Max(GRADE_LAD.last_update_date) OVER( partition BY GRADE_LAD.grade_ladder_id) AS max_update_date FROM fnd_setid_assignments fsa, fnd_setid_sets_vl fs, per_grade_ladders_f_vl GRADE_LAD, fun_all_business_units_v bu WHERE 1 = 1 AND fsa.determinant_value = bu.bu_id AND fsa.determinant_type = 'BU' AND fsa.set_id = fs.set_id AND FS.set_id = grade_set_id AND fsa.reference_group_name LIKE 'PER_GRADES' AND :EffectiveDate BETWEEN GRADE_LAD.effective_start_date AND GRADE_LAD.effective_end_date --AND GRADE_LAD.NAME LIKE '%Test%' ) t WHERE -- 全量查询分支 (:attribute = 'Full Run') -- 变更属性过滤分支 OR (:attribute = 'Changed Attributes' AND t.max_update_date >= NVL( (SELECT Max(processstart) FROM fusion.ess_request_history erh JOIN fusion.ess_request_property erp ON erh.requestid = erp.requestid WHERE state = 12 AND erp.NAME = 'reportID' AND erp.value LIKE '/Custom/Integrations/Extract.xdo' ), t.max_update_date) )
说明:
- 修复了原查询中列别名缺失的语法问题
- 将子查询的隐式连接改为显式
JOIN,提升可读性 - 逻辑清晰:
- 当
:attribute为'Full Run'时,第一个条件成立,返回全量数据 - 当
:attribute为'Changed Attributes'时,触发第二个分支的过滤逻辑 - 其他参数值时,两个条件都不满足,返回空结果(与原逻辑一致)
- 当
如果一定要用CASE WHEN写法,可采用嵌套CASE实现:
WHERE CASE WHEN :attribute = 'Full Run' THEN 1 WHEN :attribute = 'Changed Attributes' THEN CASE WHEN t.max_update_date >= NVL( (SELECT Max(processstart) FROM fusion.ess_request_history erh JOIN fusion.ess_request_property erp ON erh.requestid = erp.requestid WHERE state = 12 AND erp.NAME = 'reportID' AND erp.value LIKE '/Custom/Integrations/Extract.xdo' ), t.max_update_date) THEN 1 ELSE 0 END ELSE 0 END = 1
但嵌套CASE的可读性不如OR分支方案,优先推荐第一种写法。
内容的提问来源于stack exchange,提问作者Tech_Girl7819
相关产品推荐
相关产品推荐

