'SQL > MS-SQL' 카테고리의 다른 글
테이블 컬럼변경 (0) | 2017.09.20 |
---|---|
SELF JOIN (0) | 2017.09.19 |
LEFT OUTER JOIN / WHERE (0) | 2017.09.19 |
NULL 비교하기 (0) | 2017.09.19 |
일반집계함수 WINDOW FUNCTION (0) | 2017.09.07 |
테이블 컬럼변경 (0) | 2017.09.20 |
---|---|
SELF JOIN (0) | 2017.09.19 |
LEFT OUTER JOIN / WHERE (0) | 2017.09.19 |
NULL 비교하기 (0) | 2017.09.19 |
일반집계함수 WINDOW FUNCTION (0) | 2017.09.07 |
LEFT OUTER JOIN 시 ON 절에서는 우측(널값으로 채워지는 쪽)의 추가 제약조건을 넣고
좌측의 추가 제약조건은 WHERE절에 넣어야 한다.
1 2 3 4 5 | SELECT * --(184개 행 적용됨) FROM TBHZM200 AS A LEFT OUTER JOIN MST_TKT_STA_STOCK AS B ON a.Extn_Sta_No = b.Extn_Sta_No AND B.Oper_DT = '20090713' -- 우측의 추가 제약조건 WHERE A.Transp_Oper_Org_CD = '1' -- 좌측의 추가제약조건 | cs |
1 2 3 4 5 | SELECT * --(176개 행 적용됨) FROM TBHZM200 AS A LEFT OUTER JOIN MST_TKT_STA_STOCK AS B ON a.Extn_Sta_No = b.Extn_Sta_No AND A.Transp_Oper_Org_CD = '1' WHERE b.Oper_DT = '20090713' | cs |
1 2 3 4 5 | SELECT * --(503개 행 적용됨) FROM TBHZM200 AS A LEFT OUTER JOIN MST_TKT_STA_STOCK AS B ON a.Extn_Sta_No = b.Extn_Sta_No AND B.Oper_DT = '20090713' --둘다 ON 절에 위치함. AND A.Transp_Oper_Org_CD = '1' | cs |
1 2 3 4 5 | SELECT * --(176개 행 적용됨) FROM TBHZM200 AS A LEFT OUTER JOIN MST_TKT_STA_STOCK AS B ON a.Extn_Sta_No = b.Extn_Sta_No WHERE B.Oper_DT = '20090713' --둘다 where절에 위치 AND A.Transp_Oper_Org_CD = '1' | cs |
1 2 3 4 | 갯수 503 SELECT count(*) FROM TBHZM200 AS A 갯수 184 SELECT count(*) FROM TBHZM200 AS A WHERE A.Transp_Oper_Org_CD = '1' 갯수 13838 SELECT count(*) FROM MST_TKT_STA_STOCK AS B 갯수 178 SELECT count(*) FROM MST_TKT_STA_STOCK AS B WHERE B.Oper_DT = '20090713' | cs |
SELF JOIN (0) | 2017.09.19 |
---|---|
join Diagram (0) | 2017.09.19 |
NULL 비교하기 (0) | 2017.09.19 |
일반집계함수 WINDOW FUNCTION (0) | 2017.09.07 |
순위관련 WINDOW FUNCTION (0) | 2017.09.07 |
1 2 3 | SELECT * FROM MyTable WHERE MyColumn != NULL SELECT * FROM MyTable WHERE MyColumn <> NULL SELECT * FROM MyTable WHERE MyColumn IS NOT NULL | cs |
결론부터 말하자면, NULL은 NULL과 같지 않다
NULL은 값이 아니다.
그러므로 다른 값과 비교조차 할 수 없다.
따라서 논리 연산자를 사용하여 값을 비교할 수 없다.
SQL에서는 IS NULL과 IS NOT NULL을 명시하여 NULL을 다룰수 있다.
X IS NULL은 X가 NULL인지 아닌지 판단하는것이고
X = NULL은 X가 NULL과 같은지 판단하는 것이다. X = NULL은 절대 참이 될 수 없다.
join Diagram (0) | 2017.09.19 |
---|---|
LEFT OUTER JOIN / WHERE (0) | 2017.09.19 |
일반집계함수 WINDOW FUNCTION (0) | 2017.09.07 |
순위관련 WINDOW FUNCTION (0) | 2017.09.07 |
트리거(Trigger) (0) | 2017.09.06 |
일반 집계함수에도 OVER(), PARTITION BY를 사용할수있다!
하지만 SQL SERVER의 경우 ORDER BY를 지원하지 않는다
그룹별 소계를 구할때 유용하게 사용할수 있을것 같다.
SUM 함수를 이용해 파티션별 윈도우의 합을 구할 수 있다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | SQL > SELECT MGR, ENAME, SAL, SUM(SAL) OVER (PARTITION BY MGR) MGR_SUM FROM EMP; MGR ENAME SAL MGR_SUM ---------- ---------- ---------- ---------- 7566 FORD 3000 6000 7566 SCOTT 3000 6000 7698 JAMES 950 6550 7698 ALLEN 1600 6550 7698 WARD 1250 6550 7698 TURNER 1500 6550 7698 MARTIN 1250 6550 7782 MILLER 1300 1300 7788 ADAMS 1100 1100 7839 BLAKE 2850 8275 7839 JONES 2975 8275 7839 CLARK 2450 8275 7902 SMITH 800 800 KING 5000 5000 14 rows selected. SQL> SELECT MGR, ENAME, SAL, SUM(SAL) OVER (PARTITION BY MGR ORDER BY SAL RANGE UNBOUNDED PRECEDING) as MGR_SUM FROM EMP; MGR ENAME SAL MGR_SUM ---------- ---------- ---------- ---------- 7566 SCOTT 3000 6000 7566 FORD 3000 6000 7698 JAMES 950 950 7698 WARD 1250 3450 7698 MARTIN 1250 3450 7698 TURNER 1500 4950 7698 ALLEN 1600 6550 7782 MILLER 1300 1300 7788 ADAMS 1100 1100 7839 CLARK 2450 2450 7839 BLAKE 2850 5300 7839 JONES 2975 8275 7902 SMITH 800 800 KING 5000 5000 14 rows selected. (SQL Server의 경우 집계 함수의 경우 OVER 절 내의 ORDER BY 절을 지원하지 않는다.) | cs |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | SQL> SELECT MGR, ENAME, SAL, MAX(SAL) OVER (PARTITION BY MGR) as MGR_MAX FROM EMP; MGR ENAME SAL MGR_MAX ---------- ---------- ---------- ---------- 7566 FORD 3000 3000 7566 SCOTT 3000 3000 7698 JAMES 950 1600 7698 ALLEN 1600 1600 7698 WARD 1250 1600 7698 TURNER 1500 1600 7698 MARTIN 1250 1600 7782 MILLER 1300 1300 7788 ADAMS 1100 1100 7839 BLAKE 2850 2975 7839 JONES 2975 2975 7839 CLARK 2450 2975 7902 SMITH 800 800 KING 5000 5000 14 rows selected. SQL> SELECT MGR, ENAME, SAL FROM (SELECT MGR, ENAME, SAL, MAX(SAL) OVER (PARTITION BY MGR) as IV_MAX_SAL FROM EMP) WHERE SAL = IV_MAX_SAL ; MGR ENAME SAL ---------- ---------- ---------- 7566 FORD 3000 7566 SCOTT 3000 7698 ALLEN 1600 7782 MILLER 1300 7788 ADAMS 1100 7839 JONES 2975 7902 SMITH 800 KING 5000 8 rows selected. | cs |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | SQL> SELECT MGR, ENAME, HIREDATE, SAL, MIN(SAL) OVER(PARTITION BY MGR ORDER BY HIREDATE) as MGR_MIN FROM EMP; MGR ENAME HIREDATE SAL MGR_MIN ---------- ---------- --------- ---------- ---------- 7566 FORD 03-DEC-81 3000 3000 7566 SCOTT 09-DEC-82 3000 3000 7698 ALLEN 20-FEB-81 1600 1600 7698 WARD 22-FEB-81 1250 1250 7698 TURNER 08-SEP-81 1500 1250 7698 MARTIN 28-SEP-81 1250 1250 7698 JAMES 03-DEC-81 950 950 7782 MILLER 23-JAN-82 1300 1300 7788 ADAMS 12-JAN-83 1100 1100 7839 JONES 02-APR-81 2975 2975 7839 BLAKE 01-MAY-81 2850 2850 7839 CLARK 09-JUN-81 2450 2450 7902 SMITH 17-DEC-80 800 800 KING 17-NOV-81 5000 5000 14 rows selected. | cs |
EMP 테이블에서 같은 매니저를 두고 있는 사원들의 평균 SALARY를 구하는데,
조건은 같은 매니저 내에서 자기 바로 앞의 사번과 바로 뒤의 사번인 직원만을 대상으로 한다.
SQL Server에서는 Windowing절이 없다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | SQL> SELECT MGR, ENAME, HIREDATE, SAL, ROUND (AVG(SAL) OVER (PARTITION BY MGR ORDER BY HIREDATE ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING)) as MGR_AVG FROM EMP; MGR ENAME HIREDATE SAL MGR_AVG ---------- ---------- --------- ---------- ---------- 7566 FORD 03-DEC-81 3000 3000 7566 SCOTT 09-DEC-82 3000 3000 7698 ALLEN 20-FEB-81 1600 1425 7698 WARD 22-FEB-81 1250 1450 7698 TURNER 08-SEP-81 1500 1333 7698 MARTIN 28-SEP-81 1250 1233 7698 JAMES 03-DEC-81 950 1100 7782 MILLER 23-JAN-82 1300 1300 7788 ADAMS 12-JAN-83 1100 1100 7839 JONES 02-APR-81 2975 2913 7839 BLAKE 01-MAY-81 2850 2758 7839 CLARK 09-JUN-81 2450 2650 7902 SMITH 17-DEC-80 800 800 KING 17-NOV-81 5000 5000 | cs |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | SQL> SELECT ENAME, SAL, COUNT(*) OVER (ORDER BY SAL RANGE BETWEEN 50 PRECEDING AND 150 FOLLOWING) as SIM_CNT FROM EMP; ENAME SAL SIM_CNT ---------- ---------- ---------- SMITH 800 2 JAMES 950 2 ADAMS 1100 3 WARD 1250 3 MARTIN 1250 3 MILLER 1300 3 TURNER 1500 2 ALLEN 1600 1 CLARK 2450 1 BLAKE 2850 4 JONES 2975 3 SCOTT 3000 3 FORD 3000 3 KING 5000 1 14 rows selected. | cs |
COUNT(*)는 그룹지은 행의 총 개수를 리턴한다. 이는 NULL값과 같은 값도 포함한다.
COUNT(ALL expression) 는 그룹지은 행의 총개수를 리턴하는데 NULL값은 제외한 행의 개수를 리턴한다.
COUNT(DISTINCT expression)는 그룹지은 행의 총개수를 리턴하느데 NULL값과 같은 값을 가진 행을 제외한 행의 개수를 센다.
출처 : http://wiki.gurubee.net/pages/viewpage.action?pageId=26744104
https://docs.microsoft.com/en-us/sql/t-sql/functions/count-transact-sql
LEFT OUTER JOIN / WHERE (0) | 2017.09.19 |
---|---|
NULL 비교하기 (0) | 2017.09.19 |
순위관련 WINDOW FUNCTION (0) | 2017.09.07 |
트리거(Trigger) (0) | 2017.09.06 |
커서(Cursor) (0) | 2017.09.06 |
Rank() - 해당행에 대한 우선순위를 결정한다(중복우선순위 o)
Dense_Rank() - 해당행에 대한 우선순위를 결정한다(중복우선순위 x)
Row_number() - 조건을 만족한느 모든 행의 번호를 결정한다
OVER() - ORDER BY, GROUP BY 서브쿼리를 개선하기 위해 나온 함수
- 집계함수 뒤에서 사용하며, 집계함수 외의 컬럼을 그룹으로 묶어준다.
OVER() 에 사용되는 OPTION
1. PARTITION BY : 그룹에서 파티션을 짓는다.
2. ORDER BY DESC
3. NULLS FIRST : NULL 데이터를 먼저 출력.
4. NULLS LAST : NULL 데이터를 나중에 출력.
1 2 3 4 5 | SELECT V, RANK() OVER(ORDER BY V), DENSE_RANK() OVER(ORDER BY V), RANK() OVER(ORDER BY V) FROM #TEMP | cs |
OVER() 함수
COUNT(*)OVER() : 전체행 카운트
COUNT(*)OVER(PARTITION BY 컬럼) : 그룹단위로 나누어 카운트
MAX(컬럼)OVER() : 전체행 중에 최고값
MAX(컬럼)OVER(PARTITION BY 컬럼) : 그룹내 최고값
MIN(컬럼)OVER() : 전체행 중에 최소값
MIN(컬럼)OVER(PARTITION BY 컬럼) : 그룹내 최소값
SUM(컬럼)OVER() : 전체행 합
SUM(컬럼)OVER(PARTITION BY 컬럼) : 그룹내 합
AVG(컬럼)OVER() : 전체행 평균
AVG(컬럼)OVER(PARTITION BY 컬럼) : 그룹내 평균
STDDEV(컬럼)OVER() : 전체행 표준편차
STDDEV(컬럼)OVER(PARTITION BY 컬럼) : 그룹내 표준편차
RATIO_TO_REPORT(컬럼)OVER() : 현재행값/SUM(전체행값)
RATIO_TO_REPORT(컬럼)OVER(PARTITION BY 컬럼) : 현재행값 / SUM(그룹행값)
NULL 비교하기 (0) | 2017.09.19 |
---|---|
일반집계함수 WINDOW FUNCTION (0) | 2017.09.07 |
트리거(Trigger) (0) | 2017.09.06 |
커서(Cursor) (0) | 2017.09.06 |
UNION ALL로 소계, 합계 구하기 (0) | 2017.09.05 |
트리거(Trigger)란, 방아쇠를 당기다 라는 뜻인데, 방아쇠를 당기면 연쇄적으로 단계가 착착착 일어나서 최종적으로 총알이 발사 되듯이, 어떤 일이 발생하면 어떤일이 자동으로 발생되는 의미가 있다.
즉, SQL에서 트리거란 특정 테이블에 INSERT, DELETE, UPDATE가 발생했을 때 다른 이벤트를 처리하도록 하기위한 방법이다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | CREATE TRIGGER [NAME_OF_TRIGGER] ON [TABLE] FOR [INSERT | DELETE | UPDATE] AS BEGIN -- INSERTED에서 USER_ID를 대입하고 싶을때 DECLARE @USER_ID NVARCHAR(20) SELECT @USER_ID = USER_ID FROM INSERTED -- INSERT INSERT INTO ADDRESS VALUES(@USER_ID @NO_PHONE, GETDATE()) -- DELETE SELECT * FROM DELETED --UPDATE UPDTAE [TABLE1] SET NO_PHONE = @NO_PHONE WHERE USER_ID = @USER_ID END | cs |
MS-SQL에서는 삽입, 삭제될 행을 테이블로 관리하고있는데, 그 테이블이 INSERTED, DELETED테이블이다.
UPDATE는 UPDATED를 사용하는것이 아니라 UPDATE는 내부적으로 DELETE후 INSERT하기 때문에 DELETED테이블과, INSERTED테이블을 사용한다.
예를 들어서 기존 값이 UPDATE되었다면, 기존 값은 DELETED에 들어가고, 새로운 값은 INSERTED에 들어가게된다.
따라서 업데이트 이전의 값과 이후의 값을 DELETED와 INSERTED 테이블을 통해서 확인할 수 있다.
일반집계함수 WINDOW FUNCTION (0) | 2017.09.07 |
---|---|
순위관련 WINDOW FUNCTION (0) | 2017.09.07 |
커서(Cursor) (0) | 2017.09.06 |
UNION ALL로 소계, 합계 구하기 (0) | 2017.09.05 |
CHOOSE, IIF 논리함수 (0) | 2017.09.05 |
- 테이블에서 여러개의 행을 쿼리한 후에 쿼리의 결과인 행 집합을 한 행씩 처리하기 위한 방식이다.
- 한행씩 읽어 나간다.
- 임시테이블과 함께쓰면 각 테이블에서 원하는 데이터를 수집해서 원하는 테이블을 만들수 있다.
커서 선언(DECLARE)
커서열기(OPEN)
데이터가져오기(FETCH NEXT FROM "CURSOR_NAME" INTO 파라미터)
WHILE(@@FETCH_STATUS = 0)
(
데이터 처리(쿼리문)
데이터가져오기(FETCH NEXT FROM "CURSOR_NAME" INTO 파라미터)
)
커서 닫기(CLOSE)
커서해제(DEALLOCATE)
ERROR :
오류메시지(RAISERROR(@ERRMSG,18,1))
커서 닫기(CLOSE)
커서해제(DEALLOCATE)
RETURN
ERROR2 : 오류메시지(RAISERROR(@ERRMSG,18,1))
테스트 테이블 생성 및 데이터 입력
1 2 3 4 5 6 7 8 9 10 | create table TEST(문항int, 답변자varchar(10), 답변내용int) insert into test values (1,'홍길동',1) insert into test values (1,'갑돌이',2) insert into test values (1,'홍길동',3) insert into test values (2,'홍길동',4) insert into test values (3,'홍길동',1) insert into test values (3,'홍길동',2) insert into test values (3,'홍길동',3) | cs |
문항 답변자 답변내용
----------- ---------- -----------
1 홍길동 1
1 갑돌이 2
1 홍길동 2
2 홍길동 4
3 홍길동 1
3 홍길동 2
3 홍길동 3
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | -- 결과를입력할임시테이블 CREATE TABLE #temp(문항 INT, 답변자 VARCHAR(10), 답변내용 VARCHAR(100)) -- 커서에 사용할 변수선언 DECLARE @V_문항 INT, @V_답변자 VARCHAR(10), @V_답변내용 INT DECLARE @V_CNT INT, @V_복합답변 VARCHAR(100) --커서 선언 DECLARE MYCUR CURSOR FOR SELECT 문항,답변자,답변내용 FROM TEST ORDER BY 문항,답변자,답변내용 --커서 열기 OPEN MYCUR --첫행을 읽어서 SELECT 순서대로 변수에 대입 FETCH NEXT FROM MYCUR INTO @V_문항, @V_답변자, @V_답변내용 --첫행을 에러없이 뽑았다면 @@FETCH_STATUS 는 0을 반환한다. --더이상 읽을 행이 없다면 WHILE문을 종료한다. WHILE (@@FETCH_STATUS = 0) -- 뽑은 변수를 가지고 BEGIN-END실행 BEGIN SET @CNT = ISNULL((SELECT COUNT(*) FROM #temp WHERE 문항=@V_문항 AND 답변자=@V_답변자),0) IF @CNT = 0 BEGIN INSERT INTO #temp(문항,답변자,답변내용) values (@V_문항, @V_답변자, convert(varchar,@V_답변내용)) END ELSE BEGIN UPDATE #temp SET 답변내용=답변내용+','+convert(varchar,@P_답변내용) WHERE 문항=@V_문항 AND 답변자=V_@답변자 END -- 다음 행을 읽어서 변수로 대입한다. FETCH NEXT FROM MYCUR INTO @V_문항, @V_답변자, @V_답변내용 END -- 커서를 닫고, 할당을 해제한다. CLOSE MYCUR DEALLOCATE MYCUR --결과가 입력된 임시테이블 조회 SELECT * FROM #TEMP ORDER BY 답변자,문항 | cs |
문항 답변자 답변내용
----------- ---------- -----------
1 갑돌이 2
1 홍길동 1,3
2 홍길동 4
3 홍길동 1,2,3
순위관련 WINDOW FUNCTION (0) | 2017.09.07 |
---|---|
트리거(Trigger) (0) | 2017.09.06 |
UNION ALL로 소계, 합계 구하기 (0) | 2017.09.05 |
CHOOSE, IIF 논리함수 (0) | 2017.09.05 |
특정경우를 만족하는 행 SELECT (0) | 2017.09.04 |
1. 원하는 행을 SELECT한다.
2. UNION ALL
3. 소계를 구하고 싶은 컬럼을 GROUP BY 해서 SUM 한다.
4. UNION ALL
5. 합계를 구하고 ORDER BY로 SORTING한다.
예를들어서 A~J까지의 사람이 있고
STEP에 따라서 VALUE라는 값을 부여받을때
VALUE에 대한 소계를 구하고 이에 대한 총합을 구하기 위해서는 다음과 같이 할수있다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | SELECT A.* INTO #TEMP FROM ( SELECT 'A' NAME, '1' STEP, 100 VALUE UNION ALL SELECT 'B' NAME, '1' STEP, 100 VALUE UNION ALL SELECT 'C' NAME, '1' STEP, 100 VALUE UNION ALL SELECT 'D' NAME, '2' STEP, 200 VALUE UNION ALL SELECT 'E' NAME, '2' STEP, 200 VALUE UNION ALL SELECT 'F' NAME, '3' STEP, 300 VALUE UNION ALL SELECT 'G' NAME, '3' STEP, 300 VALUE UNION ALL SELECT 'H' NAME, '3' STEP, 300 VALUE UNION ALL SELECT 'I' NAME, '4' STEP, 400 VALUE UNION ALL SELECT 'J' NAME, '4' STEP, 400 VALUE ) | cs |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | SELECT A.NAME, A.STEP, --기준 A.VALUE, '1' SORT FROM #TEMP A UNION ALL SELECT '소계' NAME, A.STEP, --기준 SUM(VALUE), '2' SORT FROM #TEMP A GROUP BY STEP UNION ALL SELECT '합계' NAME, '9999' STEP, --기준 SUM(VALUE), '3' SORT FROM #TEMP A ORDER BY STEP, SORT | cs |
합계행을 만들때 주의해야할 점은 STEP별로 SORT를 하기때문에 STEP에 값이 없으면 맨 위로 올라가게된다.
그래서 STEP에 값을 제일 마지막 값으로 두어야하고, 이 마지막 값보다 큰 값이 있으면 안된다.
SORT를 두어서 ORDER BY시 사용하는 이유는
ORDER BY를 쓰지않은 결과물은 다음고가 같다.
여기서 STEP으로만 정렬을 하게되면
STEP으로만 정렬되기떄문에 소계행이 맨밑으로 가지 못하는 결과가 생기게된다.
따라서 SORT를 두어서 STEP으로 먼저 정렬하고 정렬된 파티션에서 또한번 SORT로 정렬한다면 소계행이 그 파티션의 맨 밑으로 들어갈수 있게 된다.
트리거(Trigger) (0) | 2017.09.06 |
---|---|
커서(Cursor) (0) | 2017.09.06 |
CHOOSE, IIF 논리함수 (0) | 2017.09.05 |
특정경우를 만족하는 행 SELECT (0) | 2017.09.04 |
FOR XML (0) | 2017.09.04 |