![](/img/trans.png)
[英]CASE WHEN SQL Query executes condition in else even if first condition is true
[英]Retrieve the First True Condition in a SQL Query
我遇到了一個問題,其中我需要根據特定條件獲取Employee的更改。
我應該僅根據以下更改檢索行:
我創建了一個表(XXTEST)來限制SQL僅引用此映射(請參閱問題末尾的DML和DDL)。
基本上,我期望的數據是:
| --------|-------------------|------------------|---------------|------------- |-------------|
| Sample | FROM_PAY_BASIS_ID | TO_PAY_BASIS_ID | FROM_CATEGORY | TO_CATEGORY | CHANGE_TYPE |
| --------| ------------------| -----------------| --------------|------------- |-------------|
| 1 | 1 | 2 | FR | FR | PAY_BASIS |
| 2 | 1 | 1 | FT | FR | ASSIGN_CAT |
| 3 | 1 | 2 | FT | FR | BOTH |
上表基於以下條件:
1. if BOTH, it should get "Assignment Category and Pay Basis" as its Change_Type
2. if Assignment Category, it should get "Assignment Category" as its Change_Type
3. if Pay Basis, it should get "Pay Basis" as its Change_Type
我希望它首先評估條件1,如果條件為假,則評估下一個條件直到最后一個條件。
當這兩個列都發生更改時,就會出現問題,導致具有3+行,其CHANGE_TYPE的值為“ PAY_BASIS”,“ ASSIGN_CAT”,“ BOTH”。
我嘗試了很多方法,但是似乎沒有什么可以完全滿足我的需求,例如以下查詢:
select *
from (select coalesce((select CHANGE_TYPE
from XXTEST
where FROM_CATEGORY = pax.EMPLOYMENT_CATEGORY
AND TO_CATEGORY = pax2.EMPLOYMENT_CATEGORY
AND FROM_ID = pax.PAY_BASIS_ID
and TO_ID = pax2.PAY_BASIS_ID),
select CHANGE_TYPE
from XXTEST
WHERE FROM_CATEGORY = pax.EMPLOYMENT_CATEGORY
AND TO_CATEGORY = pax2.EMPLOYMENT_CATEGORY
AND FROM_ID = 0
and TO_ID = 0),
select CHANGE_TYPE
from XXTEST
WHERE FROM_CATEGORY = 'N/A'
AND TO_CATEGORY = 'N/A'
AND FROM_ID = pax.PAY_BASIS_ID
and TO_ID = pax2.PAY_BASIS_ID),
NULL ) CHANGE_TYPE FROM DUAL ) CHANGE_TYPE
, PPX.FULL_NAME
, PPX.EMPLOYEE_NUMBER
from per_people_X ppx
, per_assignments_X pax
, per_assignments_X pax2
WHERE pax.assignment_id = pax2.assignment_id
AND PPX.PERSON_id = pax2.PERSON_id
AND PPX.PERSON_id = PAX.PERSON_id)
where CHANGE_TYPE is not null;
這種方法可以工作,但是無論是否有匹配項(由於NULL“ else”條件),它都會檢索所有記錄,並導致Change_Type = NULL。 是否可以僅過濾那些沒有Change_Type = NULL的記錄而不將其封裝在另一個SELECT語句中?
我也嘗試過使用CASE,如果僅更改了雇員的工資基礎ID(例如,從1更改為2),並且僅更改了雇員的類別(例如,從FT更改為FR),則它可以正常工作,但是它會評估所有情況(返回3行)無論何時發生“兩個”更改。
有什么建議嗎?
您可能在where子句中的case語句之后,例如:
SELECT PPX.FULL_NAME
, PPX.EMPLOYEE_NUMBER
, XT.CHANGE_TYPE
FROM per_people_X ppx
, XXTEST XT
, per_assignments_X pax
, per_assignments_X pax2
WHERE pax.assignment_id = pax2.assignment_id
AND PPX.PERSON_id = pax2.PERSON_id
AND PPX.PERSON_id = PAX.PERSON_id
AND (-- Both Employment Category and Pay Basis records records that were Changed
case when XT.FROM_CATEGORY = pax.EMPLOYMENT_CATEGORY
AND XT.TO_CATEGORY = pax2.EMPLOYMENT_CATEGORY
AND XT.FROM_ID = pax.PAY_BASIS_ID
AND XT.TO_ID = pax2.PAY_BASIS_ID
then 1
else 0
end = 1
OR
-- all Pay Basis records that were "Updated"
case when XT.FROM_CATEGORY = 'N/A'
AND XT.TO_CATEGORY = 'N/A'
AND XT.FROM_ID = pax.PAY_BASIS_ID
AND XT.TO_ID = pax2.PAY_BASIS_ID
then 1
else 0
end = 1
OR
-- all Assignment Category records that were "Updated"
case when XT.FROM_CATEGORY = pax.EMPLOYMENT_CATEGORY
AND XT.TO_CATEGORY = pax2.EMPLOYMENT_CATEGORY
AND XT.FROM_ID = 0
AND XT.TO_ID = 0
then 1
else 0
end = 1);
NB未經測試,因為您沒有為per_people_x或per_assignments表提供樣本數據。
您可能需要在“兩個類別”的情況表達式中添加其他條件,以排除其他兩個情況; 到目前為止,您提供的數據尚無法立即看出來。
首先,如果使用OR,則應使用方括號and (... or ... )
否則會丟失某些謂詞。 您的第一個查詢應重寫為:
SELECT PPX.FULL_NAME
, PPX.EMPLOYEE_NUMBER
, XT.CHANGE_TYPE
FROM per_people_X ppx
, XXTEST XT
, per_assignments_X pax
, per_assignments_X pax2
WHERE pax.assignment_id = pax2.assignment_id
AND PPX.PERSON_id = pax2.PERSON_id
AND PPX.PERSON_id = PAX.PERSON_id
-- THIS IS THE SECTION OF THE QUERY WHERE I'M HAVING PROBLEMS --
-- Both Employment Category and Pay Basis records records that were Changed
AND (
(XT.FROM_CATEGORY = pax.EMPLOYMENT_CATEGORY
AND XT.TO_CATEGORY = pax2.EMPLOYMENT_CATEGORY
AND XT.FROM_ID = pax.PAY_BASIS_ID
AND XT.TO_ID = pax2.PAY_BASIS_ID)
-- all Pay Basis records that were "Updated"
or (XT.FROM_CATEGORY = 'N/A'
AND XT.TO_CATEGORY = 'N/A'
AND XT.FROM_ID = pax.PAY_BASIS_ID
AND XT.TO_ID = pax2.PAY_BASIS_ID)
-- all Assignment Category records that were "Updated"
or (XT.FROM_CATEGORY = pax.EMPLOYMENT_CATEGORY
AND XT.TO_CATEGORY = pax2.EMPLOYMENT_CATEGORY
AND XT.FROM_ID = 0
AND XT.TO_ID = 0)
);
編輯:添加條件等級的解決方案
SELECT FULL_NAME
, EMPLOYEE_NUMBER
, CHANGE_TYPE
FROM (
SELECT PPX.FULL_NAME
, PPX.EMPLOYEE_NUMBER
, XT.CHANGE_TYPE
, DENSE_RANK() OVER (PRTITION BY PPX.PERSON_id,pax.assignment_id ORDER BY
CASE WHEN XT.FROM_CATEGORY = pax.EMPLOYMENT_CATEGORY
AND XT.TO_CATEGORY = pax2.EMPLOYMENT_CATEGORY
AND XT.FROM_ID = pax.PAY_BASIS_ID
AND XT.TO_ID = pax2.PAY_BASIS_ID
THEN 1
WHEN XT.FROM_CATEGORY = 'N/A'
AND XT.TO_CATEGORY = 'N/A'
AND XT.FROM_ID = pax.PAY_BASIS_ID
AND XT.TO_ID = pax2.PAY_BASIS_ID
THEN 2
ELSE 3
END
) as RNK
FROM per_people_X ppx
, XXTEST XT
, per_assignments_X pax
, per_assignments_X pax2
WHERE pax.assignment_id = pax2.assignment_id
AND PPX.PERSON_id = pax2.PERSON_id
AND PPX.PERSON_id = PAX.PERSON_id
-- THIS IS THE SECTION OF THE QUERY WHERE I'M HAVING PROBLEMS --
-- Both Employment Category and Pay Basis records records that were Changed
AND (
(XT.FROM_CATEGORY = pax.EMPLOYMENT_CATEGORY
AND XT.TO_CATEGORY = pax2.EMPLOYMENT_CATEGORY
AND XT.FROM_ID = pax.PAY_BASIS_ID
AND XT.TO_ID = pax2.PAY_BASIS_ID)
-- all Pay Basis records that were "Updated"
or (XT.FROM_CATEGORY = 'N/A'
AND XT.TO_CATEGORY = 'N/A'
AND XT.FROM_ID = pax.PAY_BASIS_ID
AND XT.TO_ID = pax2.PAY_BASIS_ID)
-- all Assignment Category records that were "Updated"
or (XT.FROM_CATEGORY = pax.EMPLOYMENT_CATEGORY
AND XT.TO_CATEGORY = pax2.EMPLOYMENT_CATEGORY
AND XT.FROM_ID = 0
AND XT.TO_ID = 0)
)
) WHERE RNK = 1;
我沒有關注您的帖子的所有詳細信息,答案和隨后的評論,但看來您可能正在追求這樣的想法。 為了在所有情況下都能得到一個准確的答案,您可能需要一個CASE
表達式。 在下面的代碼中,我使用嵌套的CASE
表達式,但這只是為了節省鍵入時間(以及執行時間)。 您可以使用單個CASE
表達式重寫它。
之所以起作用,是因為一旦在when... then...
對中找到第一個TRUE條件,評估就會立即結束。 您將必須弄清楚如何將其附加到您現有的查詢中-我僅將其輸出放在CTE中,以進行下面的測試。
with
query_output ( empl_id, from_pay_basis_id, to_pay_basis_id, from_category, to_category ) as (
select 101, 1, 2, 'FR', 'FR' from dual union all
select 102, 1, 1, 'FT', 'FR' from dual union all
select 103, 1, 2, 'FT', 'FR' from dual union all
select 104, 1, 1, 'FR', 'FR' from dual
)
select empl_id, from_pay_basis_id, to_pay_basis_id, from_category, to_category,
case when from_category != to_category then
case when from_pay_basis_id != to_pay_basis_id then 'Assignment Category and Pay Basis'
else 'Assignment Category'
end
when from_pay_basis_id != to_pay_basis_id then 'Pay Basis'
end as change_type
from query_output;
EMPL_ID FROM_PAY_BASIS_ID TO_PAY_BASIS_ID FROM_CATEGORY TO_CATEGORY CHANGE_TYPE
------- ----------------- --------------- ------------- ----------- ---------------------------------
101 1 2 FR FR Pay Basis
102 1 1 FT FR Assignment Category
103 1 2 FT FR Assignment Category and Pay Basis
104 1 1 FR FR
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.