我有两张桌子,如下:
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)
我想根据*_USED
表中的LEAVEENTITLE
值更新LEAVE_TYPE
表的LEAVES
列,例如:
LEAVE_TYPE = 'SL'
,那么我想要更新SL_USED=SL_USED + LEAVES.NO_OF_DAYS
LEAVE_TYPE = 'CL'
,那么我想要更新CL_USED=CL_USED + LEAVES.NO_OF_DAYS
答案 0 :(得分: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 :(得分:2)
不是问题的答案,但对于评论来说太大了......
尝试在父表中维护汇总数据通常不是一个好主意,因为它容易出错和混淆。例如,在这种情况下,您希望将leaves
中的值添加到_used
中的leaveentitle
值,这表示_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 Barany的更新(使用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
条记录。但最后两个选项也变得非常糟糕,尤其是当现有记录发生变化时。
一个更简单的选项是从_used
中删除_unused
和leaveentitle
列并根据需要生成值,可能是通过视图使用户的生活更轻松,查询(猜测连接条件是app_no
和ecn
,但问题不明确):
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
的分割,只需将其添加到视图中,而不必添加另一个复杂的计算层并在某处更新。