피벗(PIVOT)의 사전적 의미는 마찰을 적게 하기 위하여 회전하는 축의 지점 끝을 원뿔꼴로 한 것이다. 이 의미를 데이터베이스에서 나름 해석해보자면 테이블을 90도 회전 시켜 열을 행으로 바꿔버리는 그런 느낌의 의미라 할 수 있을 것이다.
DECLARE @COL AS NVARCHAR(MAX)
DECLARE @QUERY AS NVARCHAR(MAX)
SELECT * FROM SALE
SELECT DISTINCT
@COL = STUFF((
SELECT DISTINCT ',' + QUOTENAME(YYYYMM)
FROM SALE
FOR XML PATH('')
),1,1,'')
FROM SALE
SELECT @COL
SET @QUERY = 'SELECT * FROM
(
SELECT * FROM SALE
) AS RESULT
PIVOT( SUM(AMT) FOR YYYYMM IN ('+@COL+'))AS pivot_result'
EXECUTE(@QUERY)
우선 아래와 같이 SALE 테이블을 만들어보자
SALE TABLE
다 만들었으면 아래와 같이 코드를 만들고 실행하여 보자
SELECT DISTINCT
@COL = STUFF((
SELECT DISTINCT ',' + QUOTENAME(YYYYMM)
FROM SALE
FOR XML PATH('')
),1,1,'')
FROM SALE
SELECT @COL
STUFF, XML PATH 를 사용하여 YYYMM의 데이터를 한열로 요약하였다.
위 이미지와 같은 결과가 나타나게된다. 위의 결과를 자세히 살펴보면 YYYYMM 속성의 값들이 중복 없이 일열로 나열된 것을 확인할 수 있다. 이를 위해서 STUFF((쿼리문 FOR XML PATH('') ),1,1,'')을 활용하면 된다.
그리고 아직 설명하지 않은 QUOTENAME()이 남아있다. QUOTENAME()이 어떤 기능을 가졌는지 이해하기 위해서 우선 QUOTENAME을 없애고 위의 코드를 실행시키면 아래와 같이 [] 대괄호가 사라진 것을 확인할 수 있다. 이 사실로 미루어 보아 QUOTENAME이 대괄호를 만들어주는 역할을 수행하는 것을 알 수 있지만 왜 필요한지 의문이 들 수 있다. 어느 블로그에서 확인한 바로는 피벗 테이블에서 속성으로 만들어주기 위해서는 MSSQL에서는 대괄호로 감싸져 있어야 한다고 한다.
이제 아래와 같이 피벗 테이블을 만들어주는 쿼리문을 작성하여 보자.
SET @QUERY = 'SELECT * FROM
(
SELECT * FROM SALE
) AS RESULT
PIVOT( SUM(AMT) FOR YYYYMM IN ('+@COL+'))AS pivot_result'
EXECUTE(@QUERY)
피벗 테이블의 일반적인 구조는 아래와 같다.
SELECT *
FROM (SELECT * FROM 피벗을 원하는 테이블) AS RESULT
PIVOT ( 그룹함수(집계컬럼) FOR 피벗대상컬럼 IN ([피벗컬럼값], ...) AS PIVOT_RESULT
그리드랑 패널의 크기는 그대로 고정되어 있고 창만 늘어난 것을 확인할 수 있다. 창의 크기를 늘리기위해서 Dock이라는 것을 사용할 수 있다.
위에 버튼이 있는 패널이 panelControl2 이고 두번째 panelControl1는 textEdit이 들어가는 공간이고
밑에 GridControl1이 DB에 관련된 내용이 들어가는 곳이다.
Dock을 설정할때 나타나게 되는 창
panelControl1과 panelControl2같은 경우 위에 붙어있는 것을 확인할 수 있다. 따라서 Dock의 값을 TOP으로 설정하고
GridControl1의 Dock 값은 FIill로 주었다.
panelControl1과 panelControl2는 둘다 Dock의 값으로 TOP을 주었다. 그렇기 때문에 누가 위쪽으로 갈지 우선순위가 정해저야 한다. 위 이미지를 보면 디자이너에서 Form 컨트롤에 panel들이 추가되고 있는 모습을 볼 수 있다. 위 순서에 따라서 Dock의 우선순위가 변하기 때문에 우선순위 설정을 잘 해주어야 한다.
성공적으로 창의 크기가 커짐에 따라서 내부 컨트롤들도 커지는 것을 확인하였다. 패널 내부에있는 컨트롤들과의 간격이 너무 가까운 것 같으니 Margin의 크기를 좀더 키워서 간격을 만드는 것이 좋겠다.
SELECT
WMS.COMPANYID /*회사코드*/
,WMS.DIVISIONID /*사업장코드*/
,WMS.SOID /*수주번호*/
,WMS.CUSTOMERID /*거래처코드*/
,WMC.CUSTOMERNAME /*거래처명*/
,WMS.ORDERDATE /*수주일자*/
,WMS.DELIVERYDATE /*납기일자*/
,WML.PRICE /*수주금액*/
,WML.SOLINENO /*행번*/
,WML.ITEMID /*아이템코드*/
,WMI.ITEMNAME /*아이템명*/
,WML.ORDERQTY /*수주수량*/
,WML.SHIPQTY /*출고수량*/
,(WML.ORDERQTY - WML.SHIPQTY) AS NOTSHIPQTY /*미출고수량*/
,WML.SHIPSTATE /*출고상태*/
,WMS.REMARK /*설명*/
,WMS.ISVALID
FROM
WM_SALESORDER WMS
INNER JOIN WM_SALESORDERLINE WML ON WMS.SOID = WML.SOID AND WML.ISVALID = 'Y'
LEFT JOIN WM_CUSTOMERINFO WMC ON WMS.CUSTOMERID = WMC.CUSTOMERID AND WMS.COMPANYID = WMC.COMPANYID AND WMS.DIVISIONID = WMC.DIVISIONID
LEFT JOIN WM_ITEMINFO WMI ON WML.ITEMID = WMI.ITEMID
WHERE
WMS.COMPANYID = 1000
AND WMS.DIVISIONID = 1000
AND WMS.ORDERDATE BETWEEN '2021-01-01' AND '2021-01-30'
AND WMS.SOID LIKE '%SO%'
위 쿼리문에서 주의 깊게 봐야될 조건은 BETWEEN 조건 AND 조건 과, LIKE '%' 이다.
BETWEEN은 어떤 값보다는 작고 어떤 값보다는 큰 조건을 만들 때 편리하게 사용할 수 있다.
어떤 단어를 검색할 때 특정 키워드만 사용하고 싶으면 %를 활용하면 된다.
'-' : 글자숫자를 정해줌(EX 컬럼명 LIKE '홍_동')
'%' : 글자숫자를 정해주지않음(EX 컬럼명 LIKE '홍%')
SELECT * FROM WM_SALESORDER WHERE SOID = 'SO2011120002'
BEGIN TRAN
DELETE FROM WM_SALESORDER WHERE SOID = 'SO2011120002'
ROLLBACK TRAN
SELECT * FROM WM_SALESORDER WHERE SOID = 'SO2011120002'
위 쿼리문은 트랜잭션을 실험해보기 위함이다.
BEGIN TRAN이 실행된 뒤 다음에 실행되는 쿼리문을 ROLLBACK TRAN을 이용하여 되돌린 후 다시 SELECT문을
사용하여 DELETE되기 전으로 되돌아 갔는지 확인하였고 결과는 ROLLBACK이 성공적으로 이루어 졌다.