簡體   English   中英

檢索SQL查詢中的第一個真實條件

[英]Retrieve the First True Condition in a SQL Query

我遇到了一個問題,其中我需要根據特定條件獲取Employee的更改。

我應該僅根據以下更改檢索行:

  1. 分配類別(僅基於表xxtest中顯示的特定類別)
  2. 薪資基礎(僅從每小時到薪水和反之亦然,也顯示在表xxtest中)
  3. 薪酬基礎和工作分配類別(基於上述相同的約束)

我創建了一個表(XXTEST)來限制SQ​​L僅引用此映射(請參閱問題末尾的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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM