본문 바로가기

Database

[SQL] DML - SELECT문

1. SELECT문 : 데이터 검색, 조회

-  데이터를 조회하거나 검색할 때 사용되는 명령어
- SELECT문의 결과는 조건을 만족하는 행들의 집합
- RESULT SET: 조회된 데이터의 결과물, 조회된 행들의 집합
-  ** SELECT * : 모든 컬럼 조회

 

[표현법]
SELECT 조회하고자 하는 컬럼1, 컬럼2 .,,, 
  FROM 테이블명;
  
  
 ex)
 SELECT * 
   FROM EMPLOYEE;

 

    1. JOB테이블의 모든 컬럼 조회
    2. JOB테이블의 직급명 컬럼 조회
    3. DEPARTMENT 테이블의 모든 컬럼 조회
    4. EMPLOYEE   테이블의 직원명, 이메일 ,전화번호 , 입사일 컬럼만 조회
    5.EMPLOYEE 테이블의 입사일,직원명, 급여 컬럼만 조회
        

SELECT * FROM EMPLOYEE;
SELECT EMP_ID, EMP_NAME, SALARY FROM EMPLOYEE;

SELECT * FROM JOB;
SELECT JOB_NAME FROM JOB;
SELECT * FROM DEPARTMENT;
SELECT EMP_NAME, EMAIL, PHONE, ENT_DATE FROM EMPLOYEE;
SELECT ENT_DATE, EMP_NAME, SALARY FROM EMPLOYEE;


2. 컬럼 값을 이용한 산술연산

1) 조회하고자 하는 컬럼들을 나열하는 SELECT절에 산술연산(+,-,*,/)을 기술하여 결과를 조회할 수 있음
(나머지 연산은 불가능)
2) 산술연산 과정에서 NULL값이 있을시 산술연산 결과도 NULL (NULL + 기타 => NULL)
3) DATE타입끼리도 연산 가능 (DATE: 연, 월, 일, 시, 분, 초)
*DATE타입 중 현재시간을 구할때: SYSDATE (시분초 연산이 수행되므로 결과값이 깔끔하지 못함)

 

1. EMPLOYEE 테이블로부터 직원명, 입사일, 근무일수(오늘날짜-입사일) 조회
SELECT EMP_NAME, HIRE_DATE, SYSDATE - HIRE_DATE
  FROM EMPLOYEE;

2. EMPLOYEE테이블에서 직원명, 월급, 연봉(월급*12)조회
SELECT EMP_NAME, SALARY, SALARY*12 
  FROM EMPLOYEE;
    
3. 테이블로부터 직원명, 월급, 보너스, 보너스가 포함된 연봉 ( 월급+보너스*월급)*12
SELECT EMP_NAME, SALARY, BONUS, (SALARY+BONUS*SALARY)*12
  FROM EMPLOYEE;


3. 조회시 컬럼명 별칭 지정하기

  [표현법]
  컬럼명 AS 별칭,
  컬럼명 AS "별칭"
  컬럼명 "별칭"
  컬럼명 별칭 ,
  
  AS와 쌍따옴표는 생략 가능하나,
  별칭에 특문, 띄어쓰기가 포함될 경우 따옴표 필수!
SELECT EMP_NAME AS "사원명", SALARY "급여(월)" 
  FROM EMPLOYEE;


4. 결과값에 리터럴을 붙이는 법

임의로 지정한 문자열을(' ') SELECT절에 기술시
실제 그 테이블에 존재하는 데이터처럼 조회 가능
  SELECT EMP_ID, EMP_NAME, SALARY, '원' AS "단위"  -- '원'은 실제로 존재하지 않는 테이블 
  	FROM EMPLOYEE;    
    -- 그러나 홑따옴표를 이용하여 작성시, 실제 존재하는 컬럼처럼 홑따옴표 내부를 채워 반환

5. DISTINCT

조회하고자 하는 컬럼의 중복된 값을 딱 한번씩만 조회할 때(중복제거시)
해당 "컬럼명" 앞에 기술

 

[표현법]
  SELECT DISTINCT 조회하고자하는 컬럼
  	FROM 조회테이블


  SELECT DISTINCT DEPT_CODE 
    FROM EMPLOYEE;

6. WHERE절(조건)

조회하고자 하는 테이블으로부터,
특정 조건을 제시조건을 만족하는 데이터만 추출할 때 사용
[표헌법]
SELECT 조회하고자 하는 컬럼, 컬럼,
FROM 테이블명 
WHERE(조건식)

 SELECT * 
   FROM EMPLOYEE 
  WHERE SALARY >= 4000000;


7. 조건식에 사용되는 비교연산자, 논리연산자
<비교연산자>

>, >=, <, <=
동등비교
일치하는가: (자바에서는 ==) ' = '
일치하지 않는가 : <>, ^=, != 모두 사용가능

**문자열에는 ' ' 사용

 

1. EMPLOYEE테이블로부터 부서코드가 D9인 사원들의 사원명, 부서코드, 급여조회

SELECT EMP_NAME, DEPT_CODE, SALARY 
  FROM EMPLOYEE 
 WHERE DEPT_CODE = 'D9';  -- 오라클에서는 동등비교 "=", 문자열은 ' ' 로 감쌈

2. EMPLOYEE테이블로부터 부서코드가 D9가 아닌 사원들의 사원명, 부서코드, 급여조회
SELECT EMP_NAME, DEPT_CODE, SALARY 
FROM EMPLOYEE 
WHERE DEPT_CODE <> 'D9'; -- 오라클에서 문자데이터 사용시 따옴표 사용 ''

3. EMPLOYEE테이블로부터 급여가 300만원 이상인 사원들의 이름, 급여, 입사일 조회
SELECT EMP_NAME, SALARY, HIRE_DATE 
  FROM EMPLOYEE 
 WHERE SALARY>= 3000000;

4. EMPLOYEE테이블로부터 직급코드가 J2인 사람들의 급여,이름, 보너스 조회
SELECT SALARY, EMP_NAME, BONUS 
  FROM EMPLOYEE 
 WHERE JOB_CODE = 'J2';
 
5. EMPLOYEE테이블로부터 연봉(급여*12)이 5000만원 이상인 사원들의 
   이름, 급여, 연봉, 입사일 조회
SELECT EMP_NAME, SALARY, SALARY*12 , '원' AS "연봉" 
  FROM EMPLOYEE
 WHERE SALARY*12 > 50000000;


<논리연산자>

여러개 조건을 엮을 때 사용
AND : ~이고
BETWEEN ~ AND ~ : 몇 이상 몇 이하인 범위에 대한 조건을 제시할 때 사용
OR : ~ 또는
[표현법]

WHERE ~ AND ~ ;
WHERE ~ OR ~ ;
WHERE BETWEEN 하한값 AND 상한값


-NOT: 자바의 논리부정 연산자, 전체부정
1. 부서코드가 D9이면서 급여가 500만원 이상인 사원들의 이름, 부서코드, 급여조회

SELECT EMP_NAME, DEPT_CODE, SALARY 
  FROM EMPLOYEE
 WHERE DEPT_CODE = 'D9' 
   AND SALARY >= 5000000;


2. 부서코드가 D6이거나 급여가 300만원이상인 사원들의 이름,부서코드 ,급여
SELECT EMP_NAME, DEPT_CODE, SALARY 
  FROM EMPLOYEE
 WHERE DEPT_CODE = 'D6'
    OR SALARY >= 3000000;

3. 급여가 350~600이하 사원의 이름, 사번, 급여, 직급코드 조회
 <AND문 사용>
SELECT EMP_NAME, EMP_ID, SALARY
  FROM EMPLOYEE
 WHERE SALARY >= 3500000 
   AND SALARY <=6000000;
<BETWEEN- AND문 사용>
SELECT EMP_NAME, EMP_ID, SALARY, JOB_CODE
  FROM EMPLOYEE
 WHERE SALARY BETWEEN 3500000 AND 6000000;
4. 급여가 350미만이거나 600만원 초과인 사원들의 이름, 사번 급여, 직급코드 조회
SELECT EMP_NAME, EMP_ID, SALARY, JOB_CODE
  FROM EMPLOYEE
 WHERE SALARY NOT BETWEEN 3500000 AND 6000000;

--NOT: 자바의 논리부정 연산자, 전체부정
--BETWEEN AND연산자 -> DATE 형식 사용가능
-- 입사일이 90년도 1월 1일부터 -03년도 1월 1일인 사원들의 모든 컬럼 조회
-- 오라클에서는 ; 안붙이면 다음 줄에서 에러나는군..


5. 입사일이 90/01/01 ~ 03/01/01
SELECT * 
  FROM EMPLOYEE
 WHERE HIRE_DATE  >= '90/01/01' 
   AND HIRE_DATE <= '03/01/01';

SELECT *
  FROM EMPLOYEE
 WHERE HIRE_DATE BETWEEN '90/01/01' AND '03/01/01'; 

6. 입사일이 90/01/01 ~ 03/01/01가 아닌 사람들의 모든 컬럼
SELECT *
  FROM EMPLOYEE
 WHERE HIRE_DATE NOT BETWEEN '90/01/01' 
 AND '03/01/01';


8. LIKE '특정패턴'

- 비교하려는 컬럼 값이 내가 지정한 특정패턴을 만족할 경우 조회
- 특정 패턴에 와일드카드인 '%, '_'를 가지고 제시가능

1) %: 0글자 이상
비교대상컬럼명 LIKE 'STR%' : 컬럼값 중에서 'STR'로 시작되는 모든것
비교대상컬럼명 LIKE '%STR' : 컬럼값 중에서 'STR'로 끝나는 모든것
비교대상컬럼명 LIKE '%STR%' : 컬럼값 중에서 'STR'이 포함되는 모든 것을 조회

2) _: 1글자
비교대상컬럼명 LIKE '_문자' : 해당 컬럼값 중에서 '문자'앞에 무조건 1글자가 있을 경우 조회경우
비교대상컬럼명 LIKE '__문자' : 해당 컬럼값 중에서 '문자'앞에 무조건 2글자가 있을 경우 조회

1. 성이 전씨인 사원들의 이름, 급여, 입사일 조회
SELECT EMP_NAME, SALARY, HIRE_DATE
  FROM EMPLOYEE
 WHERE EMP_NAME LIKE '전%';

2. 이름중에 '하'가 포함된 사원 이름, 사번, 부서코드 조회
SELECT EMP_NAME, EMP_NO, DEPT_CODE
  FROM EMPLOYEE
 WHERE EMP_NAME LIKE '%하%';

3. 전화번호 4번재짜리가 9로 시작하는 사원들의 사번, 사원명, 전화번호, 이메일 조회
SELECT EMP_ID, EMP_NAME, PHONE, EMAIL
  FROM EMPLOYEE
 WHERE PHONE LIKE '___9%'

4. 이름가운데글자가 '지'인 사원들의 모든 칼럼
SELECT * 
  FROM EMPLOYEE
 WHERE EMP_NAME LIKE '_지%';


5. 이름이'연'으로 끝나는 사원들의 이름, 입사일 조회
SELECT EMP_NAME, HIRE_DATE
 FROM EMPLOYEE
WHERE EMP_NAME LIKE '%연';

6. 전화번호 처음 3글자가 010이 아닌 사원들의 이름, 전화번호조회
SELECT EMP_NAME, PHONE
  FROM EMPLOYEE
 WHERE PHONE NOT LIKE '010%';
 
7. DEPARTMENT테이블에서 해외영업과 관련된 부서들의 모든 컬럼 조회
SELECT *
 FROM DEPARTMENT
WHERE DEPT_TITLE LIKE '해외영업%';

9. IS NULL - 조건문에서 사용

[표현법]
비교대상컬럼 IS NULL : 컬럼값이 NULL일경우
비교대상컬럼 IS NOT NULL : 컬럼값이 NULL이 아닐경우

**주의 : NULL은 숫자도 문자도 아니므로, =, != 사용 불가
대신 IS NULL, NOT NULL 사용해야함
1. 보너스가 없는 사원의 사번, 이름 ,급여 ,보너스
SELECT EMP_ID, EMP_NAME, SALARY, BONUS
  FROM EMPLOYEE
 WHERE BONUS IS NULL;

2. 보너스를 받는 사원들
SELECT EMP_ID, EMP_NAME, SALARY, BONUS
  FROM EMPLOYEE
 WHERE BONUS IS NOT NULL;

3. 사수가 없는 사원들의 사원명, 사수사번, 부서코드 
SELECT EMP_NAME, MANAGER_ID, DEPT_CODE
  FROM EMPLOYEE 
 WHERE MANAGER_ID IS NULL;

4. 사수가 없고 부서배치도 받지 않은 사원들의 모든 컬럼 조회
SELECT *
  FROM EMPLOYEE
 WHERE MANAGER_ID IS NULL AND DEPT_CODE IS NULL;

10. IN

비교대상 컬럼의 "값" 중에 내가 제시한 값과 일치하는 값들을 반환
[표현법]
비교대상컬럼 IN (값1, 값2, 값3,,,);
1. 부서코드가 D5거나 D6이거나 D8이거나 D2인 사원들의 이름 ,부서코드 , 급여
 1) OR 연산자 사용
 SELECT EMP_NAME, DEPT_CODE, SALARY
   FROM EMPLOYEE
   WHERE DEPT_CODE ='D5' OR DEPT_CODE='D2' OR DEPT_CODE = 'D6' OR DEPT_CODE = 'D8';
 2) IN 사용
 SELECT EMP_NAME, DEPT_CODE, SALARY 
  WHERE DEPT_CODE IN ('D2', 'D5', 'D6', 'D8');
2. 그 외 사원들 
SELECT EMP_NAME, DEPT_CODE, SALARY
  FROM EMPLOYEE
 WHERE DEPT_CODE NOT IN ('D2', 'D5', 'D6', 'D8');


11. 연결연산자 ||

- 문자열 + 문자열
- 자바의 System.out.println("num : " +num); 문자열과 문자열을 합치는 연산자
- 여러 컬럼값들을 하나의 컬럼 내 값으로 연결하여 반환
- 컬럼과 컬럼, 컬럼과 리터럴을 연결할 수 있음
SELECT EMP_ID ||' '|| EMP_NAME ||' '|| SALARY AS "연결"
  FROM EMPLOYEE;


12. 연산자 우선순위

1) ()
2) 산술
3) 연결
4) 비교
5) IS NULL, LIKE, IN
6) BETWEEN AND 
7) AND 
8) OR  -- OR 이 우선순위가 낮음에 유의!

13. ORDER BY 절 (정렬)

- 컬럼 정렬에 사용하는 구문
- SELECT문 가장 마지막에 기입 (SELECT ~ FROM ~ WHERE ~ ORDER BY)
- 실행 순서 또한 가장 마지막
- ORDER BY 절은 SELECT절 수행 이후에 실행되기 때문에
SELECT절에서 별칭을 지으면, 해당 별칭을 ORDERBY 절에서 컬럼명 대신 사용 가능

- ASC: 오름차순정렬 (DEFAULT)
- DESC : 내림차순 정렬
- NULL FIRST: NULL값이 포함되어 있을 경우 우선배치 (내림차순시기본값)
- NULL LAST: NULL값이 포함되어 있을 경우 뒤로배치 (오름차순시 기본값)


*NULL은 
 --> oracle서버: 무한대 (가장 큰 값)으로 간주 => 내림차순시 맨 앞, 오름차순시 맨 뒤에 있음
--> sql서버: -무한대(가장 작은 값)으로 간주 => 내림차순시 맨 뒤 , 오름차순시 맨 앞에 있음
[표현법]

SELECT 조회컬럼, 컬럼 AS "별칭", 컬럼....
  FROM 테이블명
 WHERE 조건  (생략가능)
 ORDER
    BY  [정렬할컬럼/별칭/컬럼순번] [ASC/DESC] [NULLS FIRST /NULLS LAST] (생략가능)
    
    BY  [정렬할 컬럼1] [ASC/DESC] , [정렬할 컬럼2] [ASC/DESC];
    


SELECT*
  FROM EMPLOYEE
 ORDER
  --BY BONUS; -- 오름차순 정렬됨 (기본값), 오름차순의 경우 NULL LAST;
  --BY BONUS ASC NULLS FIRST;
  --BY BONUS DESC NULLS FIRST (기본값);
    BY BONUS DESC , SALARY ASC;

14. GROUP BY절

- 데이터들을 원하는 그룹으로 나누는 역할
- 중복이 존재하는 하나의 컬럼의 컬럼값들을 중복을 제거하여 반환
- 여러개의 값을 그룹별로 나누어 처리할 목적으로 사용
- GROUP BY절을 통해 그룹핑할 경우, 속성을 컬럼명으로 하는 새로운 열이 생성됨
- GROUP BY절이 있는 경우 SELECT절에서 새로운 컬럼을 가져올때에도 역시 해당 기준으로 그룹핑된 형태여야함 --> 집계함수 SUM, MIN, MAX, AVG, COUNT 등이 함께 사용
- SELECT절에는 그룹화한 속성만 올 수 있음 (집계함수 제외)
- 속성은 SELECT절과 GROUP BY 둘다 명시하여야 하나,
집계함수의 경우에는 GROUP BY절에 명시할 필요 없음
- GROUP BY절의 위치는 WHERE 와 ORDER BY절 사이에 위치한다.
(참고: (https://mine-it-record.tistory.com/36) )

 

출처:더북 https://thebook.io/006977/ch04/03/02/

---총 급여합
SELECT SUM(SALARY)
FROM EMPLOYEE;

---각 부서별 총 급여합
SELECT DEPT_CODE, SUM(SALARY)  -- 내가 그룹 기준으로 삼은 내용만 SELECT절의 필드로 쓸 수 있음
   FROM EMPLOYEE
 GROUP BY DEPT_CODE;
--전체 사원 수
SELECT COUNT(*)
  FROM EMPLOYEE;
  
-- 부서별 사원 수
SELECT DEPT_CODE AS "부서명", COUNT(*) AS "배정인원"
  FROM EMPLOYEE
 GROUP BY DEPT_CODE;
 
--- 퇴사 하지 않은 사람과 퇴사한 사람의 수 조회
 SELECT DECODE(SUBSTR(EMP_NO, 8, 1), 1, '남자', 2, '여자')  AS 성별,  COUNT(*) AS 인원 -- 내가 그룹 기준으로 삼은 내용만 SELECT절의 필드로 쓸 수 있음
   FROM EMPLOYEE
   GROUP 
       BY SUBSTR(EMP_NO, 8, 1) ;      
       
           SELECT CASE
                        WHEN ENT_DATE IS NULL THEN '재직중'
                        ELSE '퇴사' 
                  END "재직여부",
                  COUNT(*)
       FROM EMPLOYEE
     GROUP 
           BY 
                ENT_DATE;


15. HAVING절 : GROUP BY 의 조건절

- 그룹에 대한 조건을 제시하고자 할 때 사용되는 구문
- "그룹함수"를 가지고 조건을 제시할 때 사용되며, 주로 GROUP BY와 함께 쓴다
(대부분의 경우 그룹함수로 조건제시)
- WHERE과의 차이점: 실행순서가 GROUP BY보다 느림
- HAVING절에 사용된 속성도 SELECT절의 속성으로 올 수 있음
 -- 부서별 평균 급여, 300만원 이상인 부서만 조회
 
 SELECT DEPT_CODE, ROUND( AVG(SALARY) )
    FROM EMPLOYEE                                  
   WHERE AVG(SALARY) >= 3000000  --- 실행시 WHERE조건식이 GROUP BY보다 실행순서가 빨라 오류발생 
                                   -- WHERE조건절은 GROUP함수에는 쓸 수 없음
  GROUP
         BY DEPT_CODE;


<실행순서>

5. SELECT *, 조회하고자 하는 컬럼, 산술연산, 함수식, "별명"
1:  FROM 조회하고자 하는 테이블                                                             
2:  WHERE 조건식
3.  GROUP BY 나누고자 하는 그룹 기준에 해당하는 컬럼명, 함수식
4.   HAVING절 그룹 함수식에 대한 조건식
6.   ORDER BY 정렬기준에 해당하는 컬럼명, 별칭, 컬럼 순번,  ASC DESC, NULL FIRST, NULL LAST;
 --각 직급별 총 급여 합이 1000만원 이상인 직급코드, 급여합 조회
 
  SELECT JOB_CODE, SUM(SALARY)
    FROM EMPLOYEE
   GROUP 
      BY JOB_CODE 
  HAVING SUM(SALARY) > 10000000;
 
 
 ---각 부서별 보너스를 받는 사원이 한명도 없는 부서코드를 조회
 
  SELECT  DEPT_COD, COUNT BONUS
    FROM EMPLOYEE
   GROUP 
      BY DEPT_CODE  ----  내가 묶은 그룹은 부서코드임, HAVING절에는 그룹으로 묶은 것에 해당하는 값에 대해 조회
 -- HAVING SUM(BONUS) IS NULL; 
  HAVING COUNT(BONUS) = 0 ;  --- DEPT 코드에 대한 조건, DEPT코드별 COUNT가 0인 것 
  
  /
 --- ORDER BY 절은 SELECT절 수행 이후에 실행되기 때문에 SELECT절에서 별칭을 지으면, 해당 별칭을 ORDERBY 절에서 컬러명 대신 사용 가능 
  SELECT EMP_ID AS "사원ID"
  FROM EMPLOYEE
  WHERE EMP_ID >= 215
   ORDER BY 사원ID DESC;
   
----전체 사원들의 사번, 사원명, 부서코드, 부서명까지 한 번 조회해보기

 SELECT EMP_ID, EMP_NAME, DEPT_CODE --  DEPT_TITLE
   FROM EMPLOYEE;
  
  SELECT DEPT_ID, DEPT_TITLE
  FROM DEPARTMENT;
  
---전체사원들의 사번, 사원명, 직급코드, 직급명

 SELECT EMP_ID, EMP_NAME, JOB_CODE, JOB_NAME
  FROM EMPLOYEE;


+) 더미테이블 (DUMMY TABLE, DUAL)

가상테이블 ,
<FROM 테이블; > 는 SELECT와 세트이므로 생략이 불가, 조회할 테이블이 없는 경우
가상의 더미테이블 (DUMMY TABLE)로 DUAL 을 사용

FROM DUAL ;