2012-02-20 32 views
-1

我有兩個表爲下值的狀態更新值:要在表格中根據從另一個表

LEAVEENTITLE 
Name       Null  Type  
------------------------------ -------- ----------------------------------- 
CL_ENTITLED     NOT NULL NUMBER(2) 
APP_NO         NUMBER(6)     
CL_USED         NUMBER(2)   
SL_ENTITLED     NOT NULL NUMBER(2)   
SL_USED         NUMBER(2)   
LTA_ENTITLED     NOT NULL NUMBER(2)   
LTA_USED        NUMBER(2)   
ECN       NOT NULL NUMBER(6)   
CL_UNUSED        NUMBER(2)   
SL_UNUSED        NUMBER(2)   
LTA_UNSUED        NUMBER(2) 


LEAVES 
Name       Null  Type   
------------------------------ -------- ------------------------------------ 
APP_NO       NOT NULL NUMBER(6)   
ECN       NOT NULL NUMBER(6)   
FROM_DATE      NOT NULL DATE 
TO_DATE      NOT NULL DATE   
APP_DATE      NOT NULL DATE   
NO_OF_DAYS      NOT NULL NUMBER(3)   
LEAVE_TYPE      NOT NULL VARCHAR2(25)   
STATUS       NOT NULL VARCHAR2(10)   
REMARK         VARCHAR2(100) 

我想更新LEAVES表基礎上,LEAVE_TYPELEAVEENTITLE表的*_USED列,例如:

  • 如果LEAVE_TYPE = 'SL'然後我想更新SL_USED=SL_USED + LEAVES.NO_OF_DAYS
  • 如果LEAVE_TYPE = 'CL'然後我想更新CL_USED=CL_USED + LEAVES.NO_OF_DAYS
+0

什麼是app_no?申請人編號? – 2012-02-20 07:51:55

回答

2

不是一個真正的問題的答案,但太大評論...

試圖保持在一個父表捲起數據通常不是一個好主意,因爲它容易出錯和混亂。例如,在這種情況下,您想要將leaves中的值添加到leaveentitle中的_used值,這表明_used值不爲零,這反過來表明您打算多次運行它。但這意味着您可以不止一次地計數相同的leaves數據。如果我添加的數據是這樣的:

insert into leaveentitle(app_no, ecn, cl_entitled, sl_entitled, lta_entitled) 
values (1, 1234, 5, 10, 5); 

insert into leaves (app_no, ecn, from_date, to_date, app_date, 
    no_of_days, leave_type, status) 
values (1, 1234, date '2012-01-01', date '2012-01-02', date '2011-12-15', 
    2, 'SL', 'APPROVED'); 

...,然後運行類似於@Szilard巴拉尼的(與nvl()sum())我最終的更新:

select app_no, ecn, sl_entitled, sl_used, sl_unused 
from leaveentitle where app_no = 1 and ecn = 1234; 

APP_NO ECN SL_ENTITLED SL_USED SL_UNUSED 
------ ------ ----------- ------- --------- 
    1 1234   10  2 

...看起來好;但當時如果我再添leaves記錄:

insert into leaves (app_no, ecn, from_date, to_date, app_date, 
    no_of_days, leave_type, status) 
values (1, 1234, date '2012-02-01', date '2012-02-01', date '2012-01-15', 
    1, 'SL', 'BOOKED'); 

...並再次更新,我得到:

select app_no, ecn, sl_entitled, sl_used, sl_unused 
from leaveentitle where app_no = 1 and ecn = 1234; 

APP_NO ECN SL_ENTITLED SL_USED SL_UNUSED 
------ ------ ----------- ------- --------- 
    1 1234   10  5 

...這顯然是錯誤的,因爲我只用了3天,不5.(我感覺我的公司做了這樣的事情,因爲我的休假餘額很少準確)。您可以重新計算更新中的所有內容,而不是添加到現有值;或者你可以嘗試使用觸發器來更新總數;或者您可以嘗試維護狀態,以便知道哪些leaves記錄已包含在內。但最後兩個選項也變得很糟糕,尤其是當現有記錄發生變化時。

一個更簡單的方法是從leaveentitle刪除_used_unused列,並根據需要生成的值,可能是通過一個視圖,使生活更容易爲你的用戶,使用查詢像(猜的連接條件既app_noecn,但這個問題並不清楚):

select le.app_no, le.ecn, le.sl_entitled, 
    sum(case when l.leave_type = 'SL' then l.no_of_days else 0 end) as sl_used 
from leaveentitle le 
join leaves l on l.app_no = le.app_no and l.ecn = le.ecn 
group by le.app_no, le.ecn, le.sl_entitled; 

APP_NO ECN SL_ENTITLED SL_USED 
------ ------ ----------- ------- 
    1 1234   10  3 

...或者把所有的值形成的原父表:

create or replace view leaveview as 
select le.app_no, le.ecn, 
    le.sl_entitled, ls.sl_used, le.sl_entitled - ls.sl_used as sl_unused, 
    le.cl_entitled, ls.cl_used, le.cl_entitled - ls.cl_used as cl_unused, 
    le.lta_entitled, ls.lta_used, le.lta_entitled - ls.lta_used as lta_unused 
from leaveentitle le 
left join (select l.app_no, l.ecn, 
     sum(case when l.leave_type = 'SL' then l.no_of_days else 0 end) as sl_used, 
     sum(case when l.leave_type = 'CL' then l.no_of_days else 0 end) as cl_used, 
     sum(case when l.leave_type = 'LTA' then l.no_of_days else 0 end) as lta_used 
    from leaves l 
    group by l.app_no, l.ecn 
    ) ls on ls.app_no = le.app_no and ls.ecn = le.ecn; 

select * from leaveview where app_no = 1 and ecn = 1234; 

APP_NO ECN SL_ENTITLED SL_USED SL_UNUSED CL_ENTITLED CL_USED CL_UNUSED LTA_ENTITLED LTA_USED LTA_UNUSED 
------ ------ ----------- ------- --------- ----------- ------- --------- ------------ -------- ---------- 
    1 1234   10  3   7   5  0   5   5  0   5 

這也使您可以輕鬆地,僅通過將其添加到視圖,而不是增加額外的派生值,如基於status分裂的能力不得不添加另一個複雜的計算層並在某處更新。

+0

謝謝。我最終會按照你的建議繼續前進。 – Donkarnash 2012-02-20 18:53:51

2

假設APP_NO是兩個表之間的連接鍵,你可以嘗試這樣的事:

UPDATE leaveentitle le 
SET le.sl_used = le.sl_used + (
      SELECT CASE WHEN ls.leave_type = 'SL' THEN ls.no_of_days ELSE 0 END 
      FROM leaves ls 
      WHERE ls.app_no = le.app_no 
     ) 
    , le.cl_used = le.cl_used + (
      SELECT CASE WHEN ls.leave_type = 'CL' THEN ls.no_of_days ELSE 0 END 
      FROM leaves ls 
      WHERE ls.app_no = le.app_no 
     ); 

它假定leaves.app_no是主鍵;所以子查詢保證是標量的。

+1

'* _used'值是可以爲空的,所以你需要'nvl()'現有的值爲零;我假設每個權利可以有多個'leaves'記錄,所以你需要'sum()'那些? – 2012-02-20 09:56:52

相關問題