카테고리 없음

SQL BOOSTER] 4.3 WITH

garamdev 2025. 3. 29. 18:34

📚 SQL BOOSTER (유일환, DBian)

📌오라클 → PostgreSql 15로 변환

 

CHAP4. 유용한 SQL 문법

 

4.3.1 WITH

인라인ㅡ뷰와 비슷하다.

SQL의 가장 윗부분에서 사용한다.

WITH 절에서 정의된 SQL 블록들은 같은 SQL 내에서 테이블처럼 사용할 수 있다.

-- ************************************************
-- PART I - 4.3.1 SQL1
-- ************************************************

-- 고객, 아이템유형별 주문금액 구하기 – 인라인-뷰 이용
select	T0.CUS_ID,
		T1.CUS_NM,
		T0.ITM_TP,
		(select	A.BAS_CD_NM
		 from	C_BAS_CD A
		 where 	A.LNG_CD = 'KO'
		 and	A.BAS_CD_DV = 'ITM_TP'
		 and	A.BAS_CD = T0.ITM_TP) as ITM_TP_NM,
		T0.ORD_AMT
from	(
			select	A.CUS_ID,
					C.ITM_TP,
					SUM(B.ORD_QTY * B.UNT_PRC) as ORD_AMT
			from	T_ORD A
			join	T_ORD_DET B on A.ORD_SEQ = B.ord_seq
			join	M_ITM C on B.ITM_ID = C.itm_id
			where	A.ORD_DT >= '2017-02-01'::DATE
			and 	A.ORD_DT < '2017-03-01'::DATE
			group by A.CUS_ID, C.ITM_TP
		) T0
join	M_CUS T1 on T1.CUS_ID = T0.cus_id
order by T0.CUS_ID, T0.ITM_TP;


-- ************************************************
-- PART I - 4.3.1 SQL2
-- ************************************************

-- 고객, 아이템유형별 주문금액 구하기 – WITH~AS 이용
-- 반복되는 인라인ㅡ뷰를 제거해 성능을 개선하거나, 가독성을 좋게 할 수 있음 (무조건 X)
with T_CUS_ITM_AMT as (
	select	A.CUS_ID,
			C.ITM_TP,
			SUM(B.ORD_QTY * B.UNT_PRC) as ORD_AMT
	from	T_ORD A
	join	T_ORD_DET B on A.ORD_SEQ = B.ORD_SEQ
	join 	M_ITM C on B.ITM_ID = C.itm_id
	where	A.ORD_DT >= '2017-02-01'::DATE
	and 	A.ORD_DT < '2017-03-01'::DATE
	group by A.CUS_ID, C.ITM_TP
)
select	T0.CUS_ID,
		T1.CUS_NM,
		T0.ITM_TP,
		(select	A.BAS_CD_NM
		 from	C_BAS_CD A
		 where	A.LNG_CD = 'KO'
		 and	A.BAS_CD_DV = 'ITM_TP'
		 and	A.BAS_CD = T0.ITM_TP) as ITM_TP_NM,
		T0.ORD_AMT
from	T_CUS_ITM_AMT T0
join	M_CUS T1 on T1.CUS_ID = T0.CUS_ID
order by T0.CUS_ID, T0.ITM_TP;


-- ************************************************
-- PART I - 4.3.1 SQL3
-- ************************************************

-- 고객, 아이템유형별 주문금액 구하기, 전체주문 대비 주문금액비율 추가 – WITH~AS 이용
-- 같은 테이블을 WITH 절마다 반복 사용하는 것은 주의
with T_CUS_ITM_AMT as (
	select	A.CUS_ID,
			C.ITM_TP,
			SUM(B.ORD_QTY * B.UNT_PRC) as ORD_AMT
	from	T_ORD A
	join	T_ORD_DET B on A.ORD_SEQ = B.ord_seq
	join	M_ITM C on B.ITM_ID = C.ITM_ID
	where	A.ORD_DT >= '2017-02-01'::DATE
	and 	A.ORD_DT < '2017-03-01'::DATE
	group by A.CUS_ID, C.ITM_TP
),
T_TTL_AMT as ( -- T_CUS_ITM_AMT 사용 가능
	select	SUM(ORD_AMT) as ORD_AMT
	from 	T_CUS_ITM_AMT
)
select	T0.CUS_ID,
		T1.CUS_NM,
		T0.ITM_TP,
		(select	A.BAS_CD_NM
		 from	C_BAS_CD A
		 where	A.LNG_CD = 'KO'
		 and	A.BAS_CD_DV = 'ITM_TP'
		 and	A.BAS_CD = T0.ITM_TP) as ITM_TP_NM,
		T0.ORD_AMT,
		(ROUND(T0.ORD_AMT / T2.ORD_AMT * 100, 2))::text || '%' as ORD_AMT_RT
from	T_CUS_ITM_AMT T0
join	M_CUS T1 on T1.CUS_ID = T0.CUS_ID
join	T_TTL_AMT T2 on true
order by ROUND(T0.ORD_AMT / T2.ORD_AMT * 100, 2) desc;

4.3.2 WITH 절을 사용한 INSERT

-- ************************************************
-- PART I - 4.3.2 SQL1
-- ************************************************

-- 주문금액 비율 컬럼 추가
alter table S_CUS_YM add ORD_AMT_RT NUMERIC(18,3);


-- ************************************************
-- PART I - 4.3.2 SQL2
-- ************************************************

-- WITH~AS 절을 사용한 INSERT문
insert into S_CUS_YM (BAS_YM, CUS_ID, ITM_TP, ORD_QTY, ORD_AMT, ORD_AMT_RT)
with T_CUS_ITM_AMT as (
	select	TO_CHAR(A.ORD_DT, 'YYYYMM') as BAS_YM,
			A.CUS_ID,
			C.ITM_TP,
			SUM(B.ORD_QTY) as ORD_QTY,
			SUM(B.ORD_QTY * B.UNT_PRC) as ORD_AMT
	from	T_ORD A
			join T_ORD_DET B on A.ORD_SEQ = B.ORD_SEQ
			join M_ITM C on B.ITM_ID = C.ITM_ID
	where	A.ORD_DT >= '2017-04-01'::DATE
	and		A.ORD_DT < '2017-05-01'::DATE
	group by TO_CHAR(A.ORD_DT, 'YYYYMM'), A.CUS_ID, C.ITM_TP
)
, T_TTL_AMT as (
	select	SUM(A.ORD_AMT) as ORD_AMT
	from	T_CUS_ITM_AMT A
)
select	T0.BAS_YM,
		T0.CUS_ID,
		T0.ITM_TP,
		T0.ORD_QTY,
		T0.ORD_AMT,
		ROUND(T0.ORD_AMT / T2.ORD_AMT * 100, 2) as ORD_AMT_RT
from	T_CUS_ITM_AMT T0
		cross join T_TTL_AMT T2
		join M_CUS T1 on T1.CUS_ID = T0.CUS_ID;
728x90