update omittbl
set val =
(select val
from omittbl ot1
where ot1.keycol = omittbl.keycol
and ot1.seq = (select max(seq) -- 현재 레코드보다 작은 seq 중에 최고 seq를 구함
from omittbl ot2
where ot2.keycol = omittbl.keycol
and ot2.seq < omittbl.seq
and ot2.val is not null))
where val is null;
update omittbl
set val = case when val
= (select val
from omittbl o1
where o1.keycol = omittbl.keycol
and o1.seq = (select max(seq)
from omittbl o2
where o2.keycol = omittbl.keycol
and o2.seq < omittbl.seq))
then null
else val end;
update scorecols
set score_en = (select score from scorerows sr
where sr.student_id = scorecols.student_id and subject = 'en'),
score_nl = (select score from scorerows sr
where sr.student_id = scorescols.student_id and subject = 'kr'),
score_mt = (select score from scorerows sr
where sr.student_id = scorescols.student_id and subject = 'mt');
update scorecols
set (score_en, score_nl, score_mt)
= (select max(case when subject = 'en' then score else null end) as score_en,
max(case when subject = 'kr' then score else null end) as score_nl,
max(case when subject = 'mt' then score else null end) as score_mt
from scorerows sr
where sr.student_id = scorecols.student_id);
처음부터 테이블 사이에 일치하지 않는 레코드가 존재한 경우
학생은 존재하지만 과목이 없는 경우
- 레코드는 존재하지만 필요한 필드가 없는 경우
- COALESCE 함수로 null을 0으로 변경해서 대응
- 주어진 매개변수 중 좌측부터 Null 이 아닌 값 리턴
- 모두 Null 이면 우측 기본값 리턴
update scorecols
set = (score_en, score_nl, score_mt)
= (select coalesce(max(case when subject = 'en' then score else null end), 0) as score_en,
coalesce(max(case when subject = 'kr' then score else null end), 0) as score_kr,
coalesce(max(case when subject = 'mt' then score else null end), 0) as score_mt
from scorerows sr
where st.student_id = scorecols.student_id
where exists (select * from scorerows where student_id = scorecols.student_id);
update 때는 두 장소에 분산되어 있던 결합 조건을 on 구로 한 번에 끝낼 수 있음
테이블 풀 스캔 1회 + 정렬 1회
- 갱신 필드 늘어나도 변경 없음
- 성능 악화 염려 없음
merge into scorecols
using (select student_id,
coalesce(max(case when subject = 'en' then score else null end), 0) as score_en,
coalesce(max(case when subject = 'kr' then score else null end), 0) as score_kr,
coalesce(max(case when subject = 'mt' then socre else null end), 0) as score_mt
from scorerows
group by student_id) sr
on scorecols.student_id = sr.student_id
when matched then
update set scorecols.score_en = sr.score_en,
scorecols.score_kr = sr.score_kr,
scorecols.score_mt = sr.score_mt;
update scorerows
set score = (select case scorerows.subject
when 'en' then score_en,
when 'kr' then score_kr,
when 'mt' then score_mt
else null
end
from scorecols
where student_id = scorerows.student_id);
insert into stock
select brand, sale_date, price,
case sign(price -
(select price
from stock s1
where brand = stock.brand
and sale_date =
(select max(sale_date)
from stocks
where brand = stocks.brand
and sale_date < stocks.sale_date)))
when -1 then '↓'
when 0 then '↑'
when 1 then '→'
else null
end
from stocks
insert into stock
select brand, sale_date, price,
case sign(price -
max(price) over (partition by brand
order by sale_date
rows between 1 preceding and 1 preceding))
when -1 then '↓'
when 0 then '↑'
when 1 then '→'
else null
end
from stocks
update
-- 주문일 배송 예정일 차이
select o.order_i, o.order_name, orc.del_date - o.order_date as diff_days
from orders o
inner join orderreceipts orc on o.order_id = orc.order_id
where orc.del_date - o.order_date >= 3;
-- 주문번호 별 최대 지연일
select o.order_id, max(o.order_name), max(orc.del_date - o.order_date) as max_diff_days
from orders o
inner join receipts orc on o.order_id = orc.order_id
where orc.del_date - o.order_date >= 3
group by o.order_id;
다중 필드 할당
, 서브 쿼리
, case 식
, merge 구문
등 다양한 방식으로 SQL 갱신 구문 효율적으로 쓰자모델 갱신
도 염두해두자.