[SQLD (2-1)] SQL 기본(2) WHERE,GROUP BY,ORDER BY, JOIN, 내장함수,외장함수

업데이트:

개요

png

이번 포스팅은 데이터 자격 검정인 SQL 개발자(SQLD) 시험을 기반으로 공부했던 자료이다.
시험을 위한 공부이긴 했지만, 정리했던 자료가 향후에 도움이 많이 될 것 같다.


5. WHERE 절

SELECT [DISTINCT/ALL] 칼럼명 [ALIAS]
FROM 테이블명
WHERE 조건식;
  • 연산자의 종류 및 우선순위

png

png

  • 문자열 숫자열 연산자 관련

    SELECT PLAYER_NAME 선수이름, POSITION 포지션, BACK_NO 백넘버, HEIGHT 
    FROM PLAYER
    WHERE POSITION = 'MF';
      
    SELECT PLAYER_NAME 선수이름, POSITION 포지션, BACK_NO 백넘버, HEIGHT 
    FROM PLAYER
    WHERE HEIGHT >= 170;
    
    • 문자열 비교연산자는 "" 를 붙여줘야함
    • 숫자형 비교연산자는 "" 를 붙여도 HEIGHT 컬럼이 숫자형이므로 숫자로 바꿔서 인식함
  • WHERE ~ IN ~
    • JOB이 MANAGER이면서 20번 부서에 속하거나, JOB이 CLERK이면서 30번부서에 속하는 사원의 정보
    # 입력
    SELECT ENAME, JOB, DEPTNO
    FROM EMP
    WHERE (JOB, DEPTNO) IN (('MANAGER',20),('CLERK',30));
      
    [실행 결과]
    ENAME  JOB      DEPTNO
    JONES  MANAGER  20
    JAMES  CLERK    30
    
    • JOB이 MANAGER 또는 CLERK이면서, 20번 또는 30번 부서에 속하는 사원의 종류
    # 입력
    SELECT ENAME, JOB, DEPTNO
    FROM EMP
    WHERE JOB IN ('MANAGER','CLERK') AND DEPTNO IN (20,30);
      
    [실행 결과]
    ENAME  JOB      DEPTNO
    SMITH  CLERK    20
    JONES  MANAGER  20
    BLAKE  MANAGER  30
    ADAMS  CLERK    30
    JAMES  CLERK    30
    
  • WHERE ~ LIKE ~
    • % : 0개 이상의 어떤 문자를 의미
    • _ : 1개의 단일 문자를 의미
    • “장”씨 성을 가진 선수들의 정보
    SELECT PLAYER_NAME 선수이름, POSITION 포지션, BACK_NO 백넘버, HEIGHT 
    FROM PLAYER
    WHERE PLAYER_NAME LIKE '장%';
    
  • BETWEEN a AND b (a, b값 포함, 이상~이하)
    • 키가 170이상 180이하인 선수들
    SELECT PLAYER_NAME 선수이름, POSITION 포지션, BACK_NO 백넘버, HEIGHT 
    FROM PLAYER
    WHERE HEIGHT BETWEEN 170 AND 180;
    
  • IS NULL
    • NULL의 특징
      • NULL 값과의 수치연산은 NULL 값을 리턴한다.
      • NULL 값과의 비교연산은 거짓(FALSE)을 리턴한다.
      • 어떤 값과 비교할 수도 없으며, 특정 값보다 크다, 적다라고 표현할 수 없다.
      • 따라서 NULL은 IS NULL 또는 IS NOT NULL 로 비교해야함
    • 공백 '' 과 NULL값
      • Oracle : '' 을 NULL로 인식 (IS NULL 로 식별해야함)
      • SQL-Server : '' 를 그대로 '' 로 인식 ('' 로 식별해야함)
    SELECT PLAYER_NAME 선수이름, POSITION 포지션, TEAM_ID
    FROM PLAYER
    WHERE POSITION IS NULL;
    
  • AND , OR
    • 조건 : 소속팀이 삼성블루윙즈이거나 전남드래곤즈에 소속된 선수들이어야 하고, 포지션이 미드필더(MF:Midfielder)이어야 한다. 키는 170 센티미터 이상이고 180 이하여야 한다.
    SELECT PLAYER_NAME 선수이름, POSITION 포지션, BACK_NO 백넘버, HEIGHT 
    FROM PLAYER
    WHERE (TEAM_ID = 'K02' OR TEAM_ID = 'K07')
    AND POSITION = 'MF'
    AND HEIGHT >= 170
    AND HEIGHT <= 180;
    
    • 여기서 OR 보다 AND 의 처리 우선순위가 높기 때문에, 괄호를 쳐주지 않으면, TEAM_ID = ‘K02’ OR ~ 가 마지막에 생성돼서 AND 조건에 안걸리는 문제가 생김
    SELECT PLAYER_NAME 선수이름, POSITION 포지션, BACK_NO 백넘버, HEIGHT 
    FROM PLAYER
    WHERE TEAM_ID IN ('K02','K07')
    AND POSITION = 'MF'
    AND HEIGHT BETWEEN 170 AND 180;
    
    • 이렇게 IN 연산자를 쓰면 괄호를 할필요는 없음 (SQL 연산자가 NOT보다 우선임)
  • NOT , <> : 부정 연산자
    • 삼성블루윙즈 소속인 선수들 중에서 포지션이 미드필더(MF:Midfielder)가 아니고, 키가 175 센티미터 이상 185 센티미터 이하가 아닌 선수들
    SELECT PLAYER_NAME 선수이름, POSITION 포지션, BACK_NO 백넘버, HEIGHT 
    FROM PLAYER
    WHERE TEAM_ID = 'K02'
    AND NOT POSITION = 'MF'
    AND NOT HEIGHT BETWEEN 175 AND 185;
      
    # 또는
      
    SELECT PLAYER_NAME 선수이름, POSITION 포지션, BACK_NO 백넘버, HEIGHT 
    FROM PLAYER
    WHERE TEAM_ID = 'K02'
    AND POSITION <>'MF'
    AND HEIGHT NOT BETWEEN 175 AND 185;
    
  • ROWNUM : 원하는 만큼의 행을 가져올 떄 WHERE절에서 행의 개수를 제한함
    • 1개의 행만 가져오고 싶을 때,
    SELECT PLAYER_NAME FROM PLAYER WHERE ROWNUM = 1;
    # 또는
    SELECT PLAYER_NAME FROM PLAYER WHERE ROWNUM <= 1;
    # 또는
    SELECT PLAYER_NAME FROM PLAYER WHERE ROWNUM <2;
    
    • N개의 행 가져올 떄,
    SELECT PLAYER_NAME FROM PLAYER WHERE ROWNUM = N;  # 불가능
      
    SELECT PLAYER_NAME FROM PLAYER WHERE ROWNUM <= N;
    # 또는
    SELECT PLAYER_NAME FROM PLAYER WHERE ROWNUM < N+1;
    
    • 테이블 내의 고유한 키나 인덱스 값 만들때
    UPDATE MY_TABLE SET COLUMN1 = ROWNUM;
    
  • TOP : 결과 집합으로 출력되는 행의 수 제한

    TOP (Expression) [PERCENT] [WITH TIES]
    
    • Expression : 반환할 행의 수를 지정하는 숫자이다.
    • PERCENT : 쿼리 결과 집합에서 처음 Expression%의 행만 반환됨을 나타낸다.
    • WITH TIES : ORDER BY 절이 지정된 경우에만 사용할 수 있으며, TOP N(PERCENT)의 마지막 행과 같은 값이 있는 경우 추가 행이 출력되도록 지정할 수 있다.
    # 한건만 출력
    SELECT TOP(1) PLAYER_NAME FROM PLAYER;
      
    # N건만 출력
    SELECT TOP(N) PLAYER_NAME FROM PLAYER;
    


6. 함수 (Function)

  • 내장함수 (단일행 함수, 다중행 함수)
    • 단일행 함수 : 각 행(Row)들에 대해 개별적으로 작용하여, 결과도 각 행에 대해 나옴
      • SELECT, WHERE, ORDER BY, UPDATE의 SET 절에 사용 가능
      • 1:M 관계의 두 테이블을 조인하더라도 M쪽에서 출력된 해이 하나씩 단일행 함수의 입력값으로 사용되므로 사용 가능
    • 다중행 함수
      • 단일행, 다중행 함수 모두 여러 개의 인수가 입력되어도 단일값만을 반환
  • 문자형 함수

png

png

  • 오라클에서는 테이블이 필요없어도 SELECT와 FROM이 필수이므로 내장된 DUAL 테이블을 이용해야함

    SELECT LENGTH('SQL Expert')
    FROM DUAL;
    
    • 사용자 SYS가 소유하며 모든 사용자가 액세스 가능한 테이블이다.
    • SELECT ~ FROM ~ 의 형식을 갖추기 위한 일종의 DUMMY 테이블이다.
    • DUMMY라는 문자열 유형의 칼럼에 ‘X’라는 값이 들어 있는 행을 1건 포함하고 있다
  • 예제 1) 선수테이블에서 CONCAT 문자형 함수를 이용해 축구선수란 문구를 추가한다

    SELECT CONCAT(PLAYER_NAME, ' 축구선수') 선수명
    FROM PLAYER;
        
    #또는
    SELECT PLAYER_NAME || ' 축구선수' AS 선수명
    FROM PLAYER;
    
  • 예제 2) 경기장의 지역번호와 전화번호를 합친 번호의 길이구하기

    SELECT STADIUM_ID, DDD||TEL as TEL, LENGTH(DDD||TEL) as T_LEN
    FROM STADIUM;
    
    • CHR(10) : 줄바꿈 의미
    • REPLACE([문자열 또는 열], [찾을 문자], [대체할 문자(default '')])
  • 숫자형 함수

png

png

  • 소수점 이하 한자리까지 반올림하여 출력

    SELECT ENAME, ROUND(SAL/12,1), TRUNC(SAL/12,1)
    FROM EMP;
    
  • 날짜형 함수

png

png

  • 날짜형 데이터 연산

      SELECT TO_CHAR(TO_DATE('2015.01.10 10', 'YYYY.MM.DD HH24') + 1/24/(60/1), 'YYYY.MM.DD HH24:MI:SS')
      FROM DUAL;
        
      [실행 결과]
      2015.01.10 10:10:00
    
    • 1/24/60 : 1분을 의미
    • 1/24/(60/10) : 10분을 의미
    • 현재의 날짜

      SELECT SYSDATE
      FROM DUAL;
      
    • 사원(EMP) 테이블에서 입사일자에서 년,월,일 데이터를 각각 출력

      SELECT ENAME, HIREDATE,
      EXTRACT(YEAR FROM HIREDATE) 입사년도,
      EXTRACT(MONTH FROM HIREDATE) 입사월,
      EXTRACT(DAY FROM HIREDATE) 입사일
      FROM EMP;
          
      # 또는 
      SELECT ENAME, HIREDATE,
      TO_NUMBER(TO_CHAR(HIREDATE,'YYYY')) 입사년도,
      TO_NUMBER(TO_CHAR(HIREDATE,'MM')) 입사월,
      TO_NUMBER(TO_CHAR(HIREDATE,'DD')) 입사일
      FROM EMP;
      
  • 변환형 함수 : 특정 데이터 타입을 다양한 형식으로 출력하고 싶을 경우에 사용

png

png

  • 날짜를 정해진 정해진 문자 형태로 출력
  SELECT TO_CHAR(SYSDATE, 'YYYY/MM/DD') 날짜,
  TO_CHAR(SYSDATE, 'YYYY. MON, DAY') 문자형
  FROM DUAL;
  
  [실행결과]
  날짜          문자형
  ---------     ----------------
  2012-07-19    2012. 7 , 월요일
  • 금액을 달러와 원화로 표시 (L 은 로컬 화폐단위)
  SELECT TO_CHAR(123456789/1200,'$999,999,999.99') 환율반영달러,
  TO_CHAR(123456789,'L999,999,999') 원화
  FROM DUAL;
  
  [실행결과]
  환율반영달러      원화
  ------------   ----------
  $102,880.66    \123,456,789
  • CASE : if - then - else - end 조건문

png

  • SIMPLE_CASE_EXPRESSION : CASE 다음에 컬럼이나 표현식을 넣고, WHEN절에서 앞의 표현식과 비교
    • 부서 정보에서 부서 위치를 미국의 동부, 중부, 서부로 구분
    SELECT LOC,
    		CASE LOC
    				WHEN 'NEW YORK' THEN 'EAST'
    				WHEN 'BOSTON' THEN 'EAST'
    				WHEN 'CHICAGO' THEN 'CENTER'
    				WHEN 'DALLAS' THEN 'CENTER'
    				ELSE 'ETC'
    		END as AREA
    FROM DEPT;
        
    [실행 결과]
    LOC          AREA
    ---------   --------
    NEW YORK    EAST
    DALLAS      CENTER
    CHICAGO     CENTER
    BOSTON      EAST
    
  • SEARCHED_CASE_EXPRESSION : CASE 다음에 바로 WHEN절에서 조건식 활용 (더 다양하게 가능)
    • 사원 정보에서 급여가 3000 이상이면 상등급으로, 1000 이상이면 중등급으로, 1000 미만이면 하등급으로 분류
    SELECT ENAME,
    			CASE WHEN SAL >= 3000 THEN 'HIGH'
    			  	WHEN SAL >= 1000 THEN 'MID'
    					ELSE 'LOW'
    			END AS SALARY_GRADE
    FROM EMP;
        
    [실행 결과]
    ENAME      SALARY_GRADE
    --------   -------------
    SMITH      LOW
    ALLEN      MID
    WARD       MID
    .          .
    .          .
    
    # 함수형으로 중첩해서 사용해도  
    SELECT ENAME, SAL,
    			CASE WHEN SAL >= 2000
    					THEN 1000
    					ELSE (CASE WHEN SAL >= 1000
    										THEN 500
    										ELSE 0
    								END)
    			END as BONUS
    FROM EMP;
    
  • NULL 관련함수

png

  • NVL(표현식1,표현식2) : 표현식1이 NULL이면 표현식2를, NULL이 아니면 표현식 1을 출력
  SELECT NVL(NULL, 'NVL-OK') NVL_TEST
  FROM DUAL;
  
  [실행결과]
  NVL_TEST
  -------
  NVL-OK
  
  SELECT NVL('Not-Null', 'NVL-OK') NVL_TEST
  FROM DUAL;
  
  [실행결과]
  NVL_TEST
  -------
  Not-Null
  • 선수 테이블에서 성남 일화천마(K08) 소속 선수의 이름과 포지션을 출력하는데, 포지션이 없는 경우는 ‘없음’으로 표시
  SELECT PLAYER_NAME 선수명, POSITION, NVL(POSITION,'없음') 포지션
  FROM PLAYER
  WHERE TEAM_ID = 'K08'
  • 연봉계산하기 (연봉 A는 NULL값 보정이 안돼어서 연봉 출력이 안됨)
  SELECT ENAME 사원명, SAL 월급, COMM 커미션,
  (SAL * 12) + COMM 연봉A, (SAL * 12) + NVL(COMM,0) 연봉B
  FROM EMP;
  
  [실행 결과]
  사원명    월급    커미션   연봉A   연봉B
  -------   -----   ------  -----   -----
  SMITH     800                      9600
  ALLEN     1600    300     19500    19500
  WARD      1250    500     15500    15500
  JONES     2975                     35700
  • NULLIF(EXPR1, EXPR2) : EXPR1과 EXPR2가 같으면 NULL, 아니면 EXPR1을 출력
    • 사원 테이블에서 MGR와 7698이 같으면 NULL을 표시하고, 같지 않으면 MGR를 표시

      SELECT ENAME, EMPNO, MGR, NULLIF(MGR,7698) NUIF
      FROM EMP;
      
  • COALESCE(EXPR1, EXPR2, …) : NULL이 아닌 최초의 EXPR 출력, 모든 EXPR이 NULL이면 NULL 출력


7. GROUB BY, HAVING 절

  • 다중행 집계 함수
    • 여러 행들의 그룹이 모여서 그룹당 단 하나의 결과를 돌려주는 함수이다.
    • GROUP BY 절은 행들을 소그룹화 한다.
    • SELECT 절, HAVING 절, ORDER BY 절에 사용할 수 있다
    집계 함수명 ( [DISTINCT | ALL] 칼럼이나 표현식 )
    - ALL : Default 옵션이므로 생략 가능함
    - DISTINCT : 같은 값을 하나의 데이터로 간주할  사용하는 옵션임
    

png

  • GROUP BY ~ HAVING

    SELECT [DISTINCT] 칼럼명 [ALIAS]
    FROM 테이블명
    [WHERE 조건식]
    [GROUP BY 칼럼(Column)이나 표현식]
    [HAVING 그룹조건식] ;
    
    • 특징
      • GROUP BY 절을 통해 소그룹별 기준을 정한 후, SELECT 절에 집계 함수를 사용한다.
      • GROUP BY 절의 소그룹 컬럼에 NULL값이 존재해도, 이를 그룹화 해줌
      • 집계 함수의 통계 정보는 NULL 값을 가진 행을 제외하고 수행한다.
      • GROUP BY 절에서는 SELECT 절과는 달리 ALIAS 명을 사용할 수 없다.
      • 집계 함수는 WHERE 절에는 올 수 없다. (집계 함수를 사용할 수 있는 GROUP BY 절보다 WHERE 절이 먼저 수행된다)
      • WHERE 절은 전체 데이터를 GROUP으로 나누기 전에 행들을 미리 제거시킨다.
      • HAVING 절은 GROUP BY 절의 기준 항목이나 소그룹의 집계 함수를 이용한 조건을 표시할 수 있다.
      • GROUP BY 절에 의한 소그룹별로 만들어진 집계 데이터 중, HAVING 절에서 제한 조건을 두어 조건을 만족하는 내용만 출력한다.
      • HAVING 절은 일반적으로 GROUP BY 절 뒤에 위치한다.
    • HAVING 단독 사용
      • https://ggmouse.tistory.com/447
      • 테이블 전체가 한개의 그룹이 되는 경우 사용함
      • 예시 : CNT 값들 중 MAX값이 100이 넘는 것들의 총합을 계산
        SELECT SUM(CNT)
        FROM TEST_TABLE
        HAVING MAX(CNT) > 100;
      
    • 집계함수를 중첩해서 쓸 경우 주의

        # 잘못된 방법!!!
        SELECT 메뉴ID, 사용유형코드, AVG(COUNT(*)) AS AVGCNT
        FROM 시스템사용이력
        GROUP BY 메뉴ID, 사용유형코드;
      
      • 위와 같이 할 경우 오류 발생
      • AVG(COUNT(*)) 는 그룹별 카운트 후 평균값 계산으로 결과값이 1건밖에 될 수 없음
      • 그렇기 때문에 GROUP BY의 소그룹 컬럼이 올 수 없음
    • K-리그 선수들의 포지션별 통계값 (GROUP BY를 명시해야 SELECT 절의 집계함수가 인식함)

      SELECT POSITION 포지션, COUNT(*) 인원수, COUNT(HEIGHT) 키대상,
      MAX(HEIGHT) 최대키, MIN(HEIGHT) 최소키, ROUND(AVG(HEIGHT),2) 평균키
      FROM PLAYER
      GROUP BY POSITION;
      
    • K-리그 선수들의 포지션별 평균키를 구하는데, 평균키가 180 센티미터 이상인 정보만 표시
      • WHERE : 테이블 전체의 개별 행에 대한 조건
      • HAVING : 그룹 결과 집합의 행에 대한 조건 (평균키가 180이상인 그룹만 표시)
      SELECT POSITION 포지션, ROUND(AVG(HEIGHT),2) 평균키
      FROM PLAYER
      GROUP BY POSITION
      HAVING AVG(HEIGHT) >= 180;
      
    • 포지션별 평균키만 출력하는데, 최대키가 190cm 이상인 선수를 가지고 있는 포지션의 정보만 출력

      SELECT POSITION 포지션, ROUND(AVG(HEIGHT),2) 평균키
      FROM PLAYER
      GROUP BY POSITION
      HAVING MAX(HEIGHT) >= 190;
      
    • CASE 표현을 이용한 월별 데이터 집계
      • Step 1: 개별 입사정보에서 월별 데이터를 추출

        SELECT ENAME, DEPTNO, EXTRACT(MONTH FROM HIREDATE) 입사월, SAL
        FROM EMP;
        
      • Step 2: 월별 데이터 구분 (피벗팅, 월별 컬럼만들고 SAL값을 넣어줌

        SELECT ENAME, DEPTNO,
        CASE MONTH WHEN 1 THEN SAL END M01, CASE MONTH WHEN 2 THEN SAL END M02,
        CASE MONTH WHEN 3 THEN SAL END M03, CASE MONTH WHEN 4 THEN SAL END M04,
        CASE MONTH WHEN 5 THEN SAL END M05, CASE MONTH WHEN 6 THEN SAL END M06,
        CASE MONTH WHEN 7 THEN SAL END M07, CASE MONTH WHEN 8 THEN SAL END M08,
        CASE MONTH WHEN 9 THEN SAL END M09, CASE MONTH WHEN 10 THEN SAL END M10,
        CASE MONTH WHEN 11 THEN SAL END M11, CASE MONTH WHEN 12 THEN SAL END M12
        FROM (SELECT ENAME, DEPTNO, EXTRACT(MONTH FROM HIREDATE) MONTH, SAL
        FROM EMP);
              
        [실행 결과]
        ENAME DEPTNO M01 M02 M03 M04 M05 M06 M07 M08 M09 M10 M11 M12
        ------ ----- --- --- --- --- --- --- --- --- --- --- --- ---
        SMITH   20                                       800
        ALLEN   30     1600           
        WARD    30     1250           
        JONES   20           2975         
        MARTIN  30                           1250    
        BLAKE   30
              
        
      • Step3: 부서별 데이터 집계 (월별 평균)

          SELECT DEPTNO,
          AVG(CASE MONTH WHEN 1 THEN SAL END) M01,
          AVG(CASE MONTH WHEN 2 THEN SAL END) M02,
          AVG(CASE MONTH WHEN 3 THEN SAL END) M03,
          AVG(CASE MONTH WHEN 4 THEN SAL END) M04,
          AVG(CASE MONTH WHEN 5 THEN SAL END) M05,
          AVG(CASE MONTH WHEN 6 THEN SAL END) M06,
          AVG(CASE MONTH WHEN 7 THEN SAL END) M07,
          AVG(CASE MONTH WHEN 8 THEN SAL END) M08,
          AVG(CASE MONTH WHEN 9 THEN SAL END) M09,
          AVG(CASE MONTH WHEN 10 THEN SAL END) M10,
          AVG(CASE MONTH WHEN 11 THEN SAL END) M11,
          AVG(CASE MONTH WHEN 12 THEN SAL END) M12
          FROM (SELECT ENAME, DEPTNO, EXTRACT(MONTH FROM HIREDATE) MONTH, SAL
          FROM EMP)
          GROUP BY DEPTNO ;
        
    • 팀별 포지션별 FW, MF, DF, GK 포지션의 인원수와 팀별 전체 인원수를 구하기
      • SUM 함수는 기본적으로 NULL을 제외함
      • 따라서 아래 두가지를 고려해서 간단하게 만들기
        • ELSE 0 제외 → NULL로 들어감 → 알아서 제외됨
        • NVL을 제일 나중에 해서 마지막 SUM값이 NULL일 떄만 0으로 하기 (처음부터할필요 없음)
      SELECT TEAM_ID,
      NVL(SUM(CASE POSITION WHEN 'FW' THEN 1 END),0) FW,
      NVL(SUM(CASE POSITION WHEN 'MF' THEN 1 END),0) MF,
      NVL(SUM(CASE POSITION WHEN 'DF' THEN 1 END),0) DF,
      NVL(SUM(CASE POSITION WHEN 'GK' THEN 1 END),0) GK,
      COUNT(*) SUM
      FROM PLAYER
      GROUP BY TEAM_ID;
      


8. ORDER BY 절

ORDER BY 특징

  • SQL 문장으로 조회된 데이터들을 다양한 목적에 맞게 특정 칼럼을 기준으로 정렬하여 출력하는데 사용
  • 칼럼(Column)명 대신에 SELECT 절에서 사용한 ALIAS 명이나 칼럼순서를 나타내는 정수도 사용 가능 (혼용도 가능)
  • Default는 오름차순(ASC)이며, DESC 옵션으로 내림차순 가능
  • SQL 문장의 제일 마지막에 위치
  • SELECT 절에서 정의하지 않은 컬럼 사용가능
  • Oracle : NULL 값을 가장 큰 값으로 취급
  • SQL Server : NULL 값을 가장 작은 값으로 취급
  • 다중 컬럼 ) 컬럼 순서를 이용한 매핑 : SELECT 절의 컬럼 순서(?) 임

    SELECT PLAYER_NAME 선수명, POSITION 포지션, BACK_NO 백넘버
    FROM PLAYER
    WHERE BACK_NO IS NOT NULL
    ORDER BY 3 DESC, 2, 1;
    
    • 여러 컬럼을 기반으로 정렬할때는 콤마 , 로 구분하고, 옵션 입력안하면 ASC 로 들어감

SELECT 문장 실행 순서

  • 입력 순서
    • (5) SELECT 칼럼명 [ALIAS명]
    • (1) FROM 테이블명
    • (2) WHERE 조건식
    • (3) GROUP BY 칼럼(Column)이나 표현식
    • (4) HAVING 그룹조건식
    • (6) ORDER BY 칼럼(Column)이나 표현식;
  • 실행 순서
    1. 발췌 대상 테이블을 참조한다. (FROM)
    2. 발췌 대상 데이터가 아닌 것은 제거한다. (WHERE)
    3. 행들을 소그룹화 한다. (GROUP BY)
    4. 그룹핑된 값의 조건에 맞는 것만을 출력한다. (HAVING)
    5. 데이터 값을 출력/계산한다. (SELECT)
    6. 데이터를 정렬한다. (ORDER BY)
  • 관계형 데이터베이스가 데이터를 메모리에 올릴 때 행 단위로 모든 칼럼을 가져오게 되므로, SELECT 절에서 일부 칼럼만 선택하더라도 ORDER BY 절에서 다른 컬럼을 사용할 수 있는 것임
  • GROUP BY를 하면, 개별데이터를 저장하지 않고 그룹핑 기준에 사용된 칼럼과 집계 함수에 사용될 수 있는 숫자형 데이터 칼럼들의 집합을 새로 만듬
  • 따라서, 그룹핑 기준과 숫자 형식 칼럼의 집계 함수를 사용할 수 있지만, 그룹핑 기준 외의 문자 형식은 불가

    SELECT JOB
    FROM EMP
    GROUP BY JOB
    HAVING COUNT(*) >0
    ORDER BY MAX(EMPNO), MAX(MGR), SUM(SAL), COUNT(DEPTNO), MAX(HIREDATE);
    

Top N 쿼리

  • Oracle에서는 데이터를 먼저 추출하고 정렬하므로 주의

    # 이렇게 하면 3개를 뽑고 정렬함
    SELECT ENAME, SAL
    FROM EMP
    WHERE ROWNUM <4
    ORDER BY SAL DESC;
        
    # 인라인뷰로 해야 정상 동작함
    SELECT ENAME, SAL
    FROM (SELECT ENAME, SAL
          FROM EMP
          ORDER BY SAL DESC)
    WHERE ROWNUM <4 ;
    
  • SQL server에서는 TOP (Expression) [PERCENT] [WITH TIES] 로 바로 가능함

    SELECT TOP(2) ENAME, SAL
    FROM EMP
    ORDER BY SAL DESC;
        
    # WITH TIES 내림차순으로 출력하는데 같은 급여(SAL) 있으면 그것도 플러스로 출력
    SELECT TOP(2) WITH TIES ENAME, SAL
    FROM EMP
    ORDER BY SAL DESC;
    


9. 조인(JOIN)

JOIN

  • 두 개 이상의 테이블 들을 연결 또는 결합하여 데이터를 출력하는 것
  • 일반적인 경우 행들은 PRIMARY KEY(PK)나 FOREIGN KEY(FK) 값의 연관에 의해 JOIN이 성립
  • 어떤 경우에는 이러한 PK, FK의 관계가 없어도 논리적인 값들의 연관만으로 JOIN이 성립 가능
  • N개의 테이블은 순서대로 JOIN되며 N-1번의 JOIN이 필요함
  • DBMS 옵티마이저는 FROM 절에 나열된 테이블이 아무리 많아도 항상 2개의 테이블씩 짝을지어 JOIN 수행

EQUI JOIN (INNER JOIN 으로도 가능)

  • 2개의 테이블 간에 컬럼 값들이 정확히 일치하는 경우 사용
  • 보통 PK, FK 관계를 기반으로함
  • 조건은 WHERE절에 입력
  SELECT PLAYER.PLAYER_NAME, PLAYER.BACK_NO, PLAYER.TEAM_ID, TEAM.TEAM_NAME, TEAM.REGION_NAME
  FROM PLAYER, TEAM
  WHERE PLAYER.TEAM_ID = TEAM.TEAM_ID;
  
  # 또는 INNER JOIN 명시하여 사용할 수도 있다.
  SELECT PLAYER.PLAYER_NAME, PLAYER.BACK_NO, PLAYER.TEAM_ID, TEAM.TEAM_NAME, TEAM.REGION_NAME
  FROM PLAYER INNER JOIN TEAM
  ON PLAYER.TEAM_ID = TEAM.TEAM_ID;
  
  # 테이블 명이 계속 나오는 불편함을 줄이기 위해 ALIAS  테이블명에 사용
  # 주의할  : 테이블 명에 ALIAS 사용 , SELECT WHERE 무조건 ALIAS 써야함 
  SELECT P.PLAYER_NAME 선수명, P.BACK_NO 백넘버, P.TEAM_ID 팀코드, T.TEAM_NAME 팀명, T.REGION_NAME 연고지
  FROM PLAYER P, TEAM T
  WHERE P.TEAM_ID = T.TEAM_ID;

NON EQUI JOIN : 2개의 테이블 간에 컬럼 값들이 서로 정확하게 일치하지 않는 경우 사용

  • = 연산자가 아닌 BETWEEN, >, <= 등 연산자 사용
  • 예시 : 어떤 사원이 받고 있는 급여가 어느 등급에 속하는 등급인지 알고 싶다는 요구사항

png

  SELECT E.ENAME, E.JOB, E.SAL, S.GRADE
  FROM EMP E, SALGRADE S
  WHERE E.SAL BETWEEN S.LOSAL AND S.HISAL;
  • SAL 값을 LOSAL ~ HISAL 범위에서 찾는 것임

3개 이상 TABLE JOIN

  SELECT P.PLAYER_NAME 선수명, P.POSITION 포지션, T.REGION_NAME 연고지, T.TEAM_NAME 팀명, S.STADIUM_NAME 구장명
  FROM PLAYER P, TEAM T, STADIUM S
  WHERE P.TEAM_ID = T.TEAM_ID AND T.STADIUM_ID = S.STADIUM_ID
  ORDER BY 선수명;
  
  #또는 INNER JOIN 명시하여 사용할 수도 있다.
  SELECT P.PLAYER_NAME 선수명, P.POSITION 포지션, T.REGION_NAME 연고지, T.TEAM_NAME 팀명, S.STADIUM_NAME 구장명
  FROM PLAYER P INNER JOIN TEAM T
    ON P.TEAM_ID = T.TEAM_ID
      INNER JOIN STADIUM S
    ON T.STADIUM_ID = S.STADIUM_ID
  ORDER BY 선수명;


Reference

[데이터 전문가 포럼] SQL 개발자 스터디 교재

https://yurimac.tistory.com/40

댓글남기기