기능적 요구사항


[사용자]

> 회원

  • 로그인
    • 로그인
      1. 아이디와 비밀번호가 일치하면 로그인을 허용한다.
      2. 로그인이 되면 병원정보찾기, 병원예약하기, 개인(and 피보호자) 진료기록 열람 기능을 허용한다.
  • 회원가입
    • 회원가입 
      1. 회원가입시 입력 정보 목록 (* : 필수 입력사항)
        1. *회원아이디
        2. *비밀번호
        3. *이름
        4. *나이
        5. *주소
        6. *전화번호
        7. 보호자
        8. 피보호자
        9. 기저질환
        10. 복용중인 
      2. 아이디는 중복되지 않아야 한다.
      3. 회원은 중복되지 않은 회원번호가 부여되고, 회원번호로 식별된다
    • 회원탈퇴
      1. 회원탈퇴는 회원 본인만이 탈퇴가 가능하다.
      2. 회원이 탈퇴할경우 해당 회원의 정보는 모두 삭제해야한다.
        • ) 계정을 즉시 삭제하지 않고 6개월 뒤에 삭제
  • 개인정보
    • 개인정보수정
      1.  개인정보 수정은 해당 본인이거나, 보호자일 경우에만 수정이 가능하다
    • 진료기록
      1. 진료기록은 본인이거나, 보호자, 혹은 해당 병원만이 열람할 수 있다.
  • 병원검색 (리스트업을 해줄 것인지?  --- 페이징 고려)
    • 위치기반
      1. 사용자의 현위치를 gps를 통해 입력받아 반경(설정가능?) n km 이내 병원의 정보를 찾을 수 있다.
      2. 사용자가 확인할 수 있는 정보는 진료과, 영업시간, 응급실 여부, 병원위치, 병원명, 연락처, 의사정보가 있다.
    • 검색어 기반 > 다양한 필터 사용
      1. 사용자는 주소 검색을 통해 병원의 정보를 찾을 수 있다.
      2. 사용자는 확인할 수 있는 정보는 진료과, 영업시간, 응급실 여부, 병원위치, 병원명, 연락처, 의사정보가 있다.
    • 병원검색시 정보 조회 목록
      • 기본정보
        1. 병원이름
        2. 텍스트주소
        3. 상세정보
          1. 병원이름
          2. 진료과목
          3. 텍스트주소
          4. 병원정보
          5. 시설
          6. 병원번호
          7. 병원소개
          8. 진료시간
            • 점심시간
            • 요일별진료시간
            • 공휴일
          9. 공지사항
          10. 진료항목
          11. 의사정보
      • 필터
        1. 주차장 여부
        2. 전문의 여부
        3. 병원 정보
          1. 영유아검진
          2. 여의사
          3. 종합병원
          4. 전문병원
          5. 예방접종
          6. 건강검진
        4. 병원시설
          1. 일반/중환자실
          2. 일반병실
          3. 상급병실
          4. 신생아중환자실
          5. 분만실
          6. 수술실
          7. 응급실
          8. 물리치료실
        5. 병원장비
          1. CT
          2. MRI
          3. 골밀도검사기
          4. 양전자단층촬영기
          5. 유방촬영장치
          6. 종양치료
          7. 체외충격기/파쇄석기
          8. 초음파영상진단기
          9. 콘빔CT
          10. 혈액투석을위한인공신장기
        6. 진료과목
          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. 조산원
      • 의사정보
        1. 이름
        2. 성별
        3. 진료과
        4. 근무일
        5. 양력
  • 병원 예약
    • 예약
      1. 사용자는 동일한 시간에 여러개의 병원을 예약할 수 없다.
      2. 사용자는 해당 병원 예약 가능한 시간대에만 예약을 할 수 있다.
      3. 사용자는 예약을 할 때 예약시간, 증상, 담당의사선택 을 입력해야한다.
        1. 사용자가 필요로하는 진료과를 선택한다.
        2. 일주일 이내 예약 시간을 선택(30분 단위로 시간이 존재) 
        3. 불가능한 예약 시간(휴무, 이미 예약된 시간)은 선택이 불가능하다.
        4. 예약 시간을 선택했다면 그 시간대에 가능한 의사를 선택할 수 있도록 한다.
        5. 간단히 증상을 입력한다.
        6. 모든 정보가 입력이 되었다면 병원으로 예약 신청이 전송된다.
        7. 병원은 사용자로 부터 받은 예약 신청을 확정 or 반려할 수 있다.
        8. 병원 예약 신청을 확정하면 사용자로에게 알림과 예약정보를 전달한다.
      4. 보호자가 피보호자의 진료를 예약할때에는 피보호자ID와 피보호자ID를 예약정보에 기록해야한다.
      5. 사용자는 예약한 병원이 자신의 정보를 열람할 수 있도록 해야한다.
      6. 예약 정보는 보호자, 본인, 병원만이 열람할 수 있다.
      7. 사용자가 병원을 예약하면 예약번호, 예약 정보를 유지해야한다.
    • 취소
      1. 예약 취소는 예약한 본인이나 보호자, 해당 병원만이 가능하다.
      2. 예약 취소를 할때에는 예약번호, 회원아이디, 비밀번호가 필요하다.
      3. 보호자가 피보호자의 진료를 예약했을때에는 피보호자 또한 취소가 가능하다.
      4. 취소할경우에 병원과 본인, 보호자 모두에게 알림이 간다. > 트리거 사용
      5. 사용자가 예약을 취소하면 해당 예약번호의 정보들을 삭제해야한다. > 예약 status(신청, 확정, 예약반려, 진료완료, 취소)
    •  변경
      1. 예약 변경은 예약한 본인이나 보호자만이 가능하다
      2. 예약을 변경할때에는 예약번호, 회원아이디, 비밀번호가 필요하다.
      3. 보호자가 피보호자의 진료를 예약했을때에는 피보호자 또한 변경이 가능하다.
      4. 변경할 경우 병원과 본인, 보호자 모두에게 알림이 간다.  > 트리거 사용
      5. 사용자가 예약을 변경할 경우에는 해당 예약 정보를 변경해야한다. > 어떻게 바꿀지 찾아보기
  • 보호자 기능
    • 유저는 보호자, 피보호자(회원일 경우) 관계설정을 통해 보호자 서비스를 이용할 수 있다.
    • 보호자와 피보호자의 관계설정은 보호자가 피보호자의 정보를 등록하는걸로 한다.
    • 피보호자는 아내, 남편, 아이, 부모 모두 가능하나, 피보호자가 회원인 경우로 제한한다.

[병원]

  • 로그인
    • 로그인
      1. 이이디와 비밀번호가 일치하면 로그인을 허용한다.
      2. 로그인이 되면 예약자의 정보, 병원정보수정이 가능하다.
  • 회원가입
    • 회원가입
      1. 회원가입시 입력 정보 목록 (* : 필수 입력사항)
        1. *회원아이디
        2. *비밀번호
        3. *병원이름
        4. *병원주소
        5. *병원 연락처
        6. *병원 정보
        7. *병원 시설
        8. *병원 장비
        9. 진료시간
        10. 공지사항
        11. *진료과목
        12. *의사정보
        13. 병원소개
      2. 아이디는 중복되지 않아야 한다.
      3. 병원은 중복되지 않은 병원번호가 부여되고, 병원번호로 식별된다
  • 정보 열람 및 수정
    • 병원정보수정
      1.  병원정보 수정은 해당 병원만 수정이 가능하다.
      2.  병원정보 수정은 해당 병원의 아이디와 비밀번호가 필요로한다.
    • 환자정보
      1. 병원은 해당 병원을 이용했던 사용자의 정보(이름, 진료날짜, 증상)를 유지해야한다.
    • 병원 삭제
      1. 등록된 병원을 삭제하는 것은 해당 병원만이 가능하다.
      2. 등록된 병원을 삭제할 시에는 해당 병원의 아이디와 비밀번호가 필요하다.
  • 예약
    • 예약일정관리
      1. 영업시간에 회원으로부터 오직 영업시간에만 예약을 받을 수 있다.
      2. 병원은 회원으로부터 아직 예약되지 않은 시간에만 예약을 받을 수 있다. 
        • 예약정보관리
          1. 병원은 예약받은 환자의 정보(예약날짜/시간, 증상, 예약자 정보)를 유지해야한다.
          2. 예약정보는 해당 환자와 보호자, 병원만이 연람이 가능하다.

비기능적 요구사항


  • 보안
    • 시스템은 사용자 정보와 예약 데이터를 안전하게 처리하고 보호해야 한다.
  • 접근성
    • 시스템은 다양한 디바이스(스마스폰, 태플릿, PC)에서 접근이 가능해야 한다.
  • 신뢰성
    • 시스템은 고가용성을 보장하며, 데이터 오류 없이 정확하게 운영되어야 한다.
  • 사용성
    • 시스템 인터페이스는 직관적이고 사용하기 쉬어야 한다.

 

 

추가 고려사항


  • 병원 검색은 회원가입을 하지 않은 유저도 병원 검색 기능은 사용이 가능하다.
  • 보호자, 피보호자 관계 설정은 누가 어떤식으로 할 것인지 > 보호자가 피보호자(상관없음)
  • 진료예약 > 보호자가 피호자에 대해 예약을 했다면 보호자ID와 피보호자ID 기록

DB 모델링

 


1. 데이터 모델링

  • 데이터 모델링은 업무보다는 데이터를 중심으로 모델링을 진행하는 방법
  • 데이터 모델링은 일반적으로 개념적 모델링, 논리적 모델링, 물리적 모델링 3가지 과정으로 분류

 

2. 개념적 모델링 

  • 요구분석 단계에서 정의된 핵심 개체와 그들 간의 관계를 바탕으로 ERD를 생성하는 단계
    • ERD :  Entity Relationship Diagram

2.1. 엔티티(Entity)

  • 엔티티란 실제로 관리해야 할 구체적인 대상을 의미
    • 유형 엔티티 : 물리적인 형태가 있는 엔티티
    • 무형 엔티티 : 물리적인 형태는 없지만 개념적으로 존재

 

2.2. 속성(Attribute)

  • 속성이란 엔티티가 가지고 있는 특징을 의미 (최소 데이터 단위)

2.2.1. 주 식별자
  • 엔티티에 있는 데이터들을 서로 구분을 해 줄 수 있는 속성을 의미  (기본키에 해당)
    • 반드시 값이 존재
    • 값이 중복되어서는 안됨
2.2.2. 보조 식별자
  • 보조 식별자는 주 식별자를 대체할 수 있는 또 다른 속성을 의미
2.2.3. 외래 식별자 (외래키에 해당)
  • 엔티티와의 관계를 연결해 주는 식별자를 외부 식별자라고 함
    • 값이 없어도 가능
    • 주 식별자 or 보조 식별자와 연결

 

2.3. 관계(Relationship)

2.3.1. 일대일(1:1, One To One) 관계
  • A 엔티티에 존재하는 1건의 데이터와 대응되는 B 엔티티의 데이터도 1건일 경우

학생tbl 학번 / 교수tbl번호 > 주 시별자 학생tbl > 외래 식별자

2.3.2. 일대다(1:M, One To Many) 관계
  • A 엔티티에 존재하는 1건의 데이터와 대응되는 B 엔티티의 데이터가 여러 건일 경우

2.3.3. 다대다(M:M, Many To Many) 관계
  • A 엔티티에 존재하는 여러 건의 데이터와 대응되는 B 엔티티의 데이터가 여러 건일 경우 M:M 관계

수강과목 tbl 학번, 학과번호 > 식별관계


식별관계 > 학번과 과목번호 모두 값이 존재해야지 데이터가 저장
비식별관계 > 학번과 과목번호 값이 존재하지 않아도 데이터가 저장

2.3.4. 식별, 비 식별 관계
  • 식별 관계는 부모 엔티티의 주 식별자를 자식 엔티티의 주 식별자, 외래 식별자로 사용하는 관계
  • 비 식별 관계는 부모 엔티티의 주 식별자를 자식 엔티티의 외래 식별자로만 사용하는 관계
  • 비 식별자로 설계하여 작업을 하다가 오류가 발생하면 식 별자로 사용

 

 

3. 논리적 모델링

 
  • 개념적 모델링 과정에서 추상화된 데이터를 구체화하여 개체, 속성을 테이블화하고 상세화 하는 과정

3.1. 이상 (Anomaly)

  • 정규화를 진행하지 않은 엔티티를 대상으로 삽입, 갱신, 삭제 시 발생할 수 있는 예기치 못한 현상을 이상이라고 함
  • 이상에는 삽입 이상, 갱신 이상, 삭제 이상이 존재

3.1.1. 삽입 이상

 

  • 주문에 대한 정보만 입력해도 제품에 대한 정보도 같이 입력해야 함
  • 제품에 대한 정보만 입력하고 싶을 때 주문에 대한 정보는 NULL 값을 가짐

3.1.2. 갱신이상

  • 동일한 제품명을 중복되어 있는 수만큼 수정해야함
  • 한번만 수정하거나 일부만 수정할 경우 일관성이 맞지 않는 문제가 발생

3.1.3. 삭제 이상

  • 주문에 대한 정보(주문 번호, 주문 수량)를 삭제할 때 제품 번호, 제품명, 단가도 같이 삭제

3.2. 제 1 정규화

  • 하나의 속성이 하나의 값을 갖도록 함

제 1 정규화 예시

3.3. 제 2 정규화

  • 주 식별자 전체에 종속적이지 않는 속성을 분리 (주 식별자가 복합 식별자일 경우)
    • 제 2정규화 이전에 제 1 정규화를 만족해야함

제 2 정규화 예시

 

3.4. 제 3 정규화

    • 주 식별자에 종속적이지 않고 다른 속성에 종속적인 속성을 분리

제 3 정규화 예시

 

 

4. 물리적 모델링

4.1. 물리적 모델링

  • 논리적 모델링 과정에서 표현된 데이터를 실제 데이터베이스에 맞도록 구현하는 과정

  • 엔티티의 속성은 모두 테이블의 컬럼으로 생성
  • 주 식별자는 모두 테이블의 Primary Key로 지정
  • 보조 식별자는 Unique Key로 지정
  • 외부 식별자는 Foreign Key로 지정
  • 추가로 필요한 객체(뷰, 인덱스 등)를 생성
더보기

<테이블 정의서 작성>

 

 

4.2. 반 정규화

  • 반 정규화란 이름 그대로 정규화의 반대
  • A 테이블과 B 테이블이 있을 때 두 테이블을 따로 분리해도 되고 합쳐도 되는 상황이라면 분리하는 것보다 합치는 것이 성능에 더 좋을 수 있음음

 

 

 

 

 

 

실습 문제

Q1. usertbl 테이블과 buytbl 테이블을 조인하여 JPY라는 아이디를 가진 회원의 이름, 주소, 연락처, 주문 상품 이름을 조회하시오.

더보기
SELECT u.NAME AS '이름',
	u.addr AS '주소',
	CONCAT(u.mobile1, u.mobile2) AS '연락처',
	b.prodName AS '주문 상품'
FROM usertbl u
INNER JOIN buytbl b ON u.userID = b.userID
WHERE u.userID = 'JYP';

 

Q2. employee 테이블과 department 테이블을 조인하여 보너스를 받는 사원들의 사번, 직원명, 보너스, 부서명을 조회하시오.

더보기
SELECT e.emp_id AS '사번',
	e.emp_name AS '직원명',
	e.bonus AS '보너스',
	d.dept_title AS '부서명'
FROM employee e
INNER JOIN department d ON e.dept_code = d.dept_id
WHERE e.bonus IS NOT NULL;

 

Q3. employee 테이블과 department 테이블을 조인하여 인사관리부가 아닌 사원들의 직원명, 부서명, 급여를 조회하시오.

더보기
SELECT e.emp_name AS '직원명',
	d.dept_title AS '부서명',
	e.salary AS '급여'
FROM employee e
INNER JOIN department d ON e.dept_code = d.dept_id
WHERE d.dept_title != '인사관리부';

 

Q4. employee 테이블과 department 테이블, job 테이블을 조인하여 사번, 직원명, 부서명, 직급명 조회하시오.

더보기
# ['employee' JOIN 'department'] JOIN 'job'
# 순서가 잘못되면 JOIN이 안될 수도 있음

SELECT e.emp_id AS '사번',
	e.emp_name AS '직원명',
	d.dept_title AS '부서명',
	j.job_name AS '직급명'
FROM employee e
INNER JOIN department d ON e.dept_code = d.dept_id
INNER JOIN job j ON e.job_code = j.job_code;

 

Q5. 70년대생 이면서 여자이고, 성이 전 씨인 직원들의 직원명, 주민번호, 부서명, 직급명을 조회하시요.

더보기
SELECT e.emp_name AS '직원명',
	e.emp_no AS '주민번호',
	d.dept_title AS '부서명',
	j.job_name AS '직급명'
FROM employee e
INNER JOIN department d ON e.dept_code = d.dept_id
INNER JOIN job j ON e.job_code = j.job_code
WHERE e.emp_no LIKE '7%'
	AND SUBSTRING(e.emp_no, 8, 1) = 2
	AND e.emp_name LIKE '전%'
;

 

Q6. 각 부서별 평균 급여를 조회하여 부서명, 평균 급여를 조회 단 부서 배치가 안된 사원들의 평균도 같이 나오게끔 조회하시오.

더보기
SELECT IFNULL(d.dept_title, '부서없음')AS '부서명',
	FLOOR(AVG(e.salary)) AS '평균 급여'
FROM employee e
LEFT OUTER JOIN department d ON e.dept_code = d.dept_ID
GROUP BY d.dept_title
ORDER BY d.dept_title
;

 

Q7. 각 부서별 총 급여의 합이 1000만원 이상인 부서명, 급여의 합을 조회하시오.

더보기
SELECT d.dept_title AS '부서명',
	SUM(e.salary) AS '급여의 합'
FROM employee e
INNER JOIN department d ON e.dept_code = d.dept_ID
GROUP BY d.dept_title
HAVING SUM(e.salary) >= 10000000
ORDER BY SUM(e.salary) DESC
;

 

Q8. 이름에 '형'자가 들어있는 직원들의 사번, 직원명, 직급명을 조회하시오.

더보기
SELECT e.emp_id AS '사번',
	e.emp_name AS '직원명',
	j.job_name AS '직급명'
FROM employee e
INNER JOIN job j ON e.job_code = j.job_code
WHERE e.emp_name LIKE '%형%';

 

Q9.  해외영업팀에 근무하는 직원들의 직원명, 직급명, 부서 코드, 부서명을 조회하시오.

더보기
SELECT e.emp_name AS '직원명',
	j.job_name AS '직급명',
	e.dept_code AS '부서코드',
	d.dept_title AS '부서명'
FROM employee e
INNER JOIN department d ON e.dept_code = d.dept_id 
INNER JOIN job j ON e.job_code = j.job_code
WHERE d.dept_title LIKE '해외영업%'
ORDER BY d.dept_title
;

 

Q10.  각 부서별 최소 급여를 받는 사원들의 사번, 이름, 부서코드, 급여를 조회하시오.

더보기
SELECT emp_id AS '사번',
	emp_name AS '사원명',
	IFNULL(dept_code, '부서없음') AS '부서코드',
	salary AS '급여'
FROM employee
WHERE (salary, IFNULL(dept_code, '부서없음')) IN (
	SELECT MIN(salary), IFNULL(dept_code, '부서없음')
	FROM employee
	GROUP BY dept_code
)
ORDER BY dept_code
;

 

Q11. 각 직급별로 최소 급여를 받는 사원들의 사번, 이름, 직급코드, 급여 조회하시오.

더보기
SELECT emp_id AS '사번',
	emp_name AS '사원명',
	job_code AS '직급코드',
	salary AS '급여'
FROM employee
WHERE (salary, job_code) IN (
	SELECT MIN(salary), job_code
	FROM employee
	GROUP BY job_code
)
ORDER BY job_code
;

조인(JOIN)과 UNION 연산자


1. 조인

  • 조인이란 두 개 이상의 테이블을 서로 묶어서 하나의 결과 집합으로 만들어 내는 것

 

2. 내부 조인(INNER JOIN)

  • 조인 중에서 가장 많이 사용되는 조인으로 일반적으로 조인이라고 이야기하는 것이 이 내부 조인(INNER JOIN)을 지칭하는 것
  • FROM 절 다음에 INNER JOIN 구문을 통해 조인에 사용할 테이블을 기술하고 ON 절에 조인 조건을 작성
SELECT *
FROM employees e
INNER JOIN departments d ON e.dept_no = d.dept_no;
<ex1>
-- INNER JOIN 실습
-- 각 사원들의 사번, 직원명, 부서코드, 부서명을 조회
# e와 d는 각각 employee 테이블과 department 테이블의 별칭

SELECT emp_id AS '사번',
	emp_name AS '직원명',
	dept_code AS '부서코드',
	dept_title AS '부서명'
FROM employee e
INNER JOIN department d ON dept_code = d.dept_id;


<ex2-1>
-- 각 사원들의 사번, 직원명, 직급 코드, 직급명을 조회
# job_code가 컬럼 이름이 두개의 테이블에서 모두 동일하기 때문에
# 에러가 발생

SELECT emp_id AS '사번',
	emp_name AS '직원명',
	job_code AS '직급 코드',
	job_name AS '직급명'
FROM employee
INNER JOIN job ON job_code = job_code;

 

에러 발생


<ex2-2>
-- 각 사원들의 사번, 직원명, 직급 코드, 직급명을 조회
-- 방법 1) 테이블명 언급

SELECT employee.emp_id AS '사번',
	employee.emp_name AS '직원명',
	employee.job_code AS '직급 코드',
	job.job_name AS '직급명'
FROM employee
INNER JOIN job ON employee.job_code = job.job_code;

방법 1


<ex2-3>
-- 각 사원들의 사번, 직원명, 직급 코드, 직급명을 조회
-- 방법 2) 별칭 사용

SELECT e.emp_id AS '사번',
	e.emp_name AS '직원명',
	e.job_code AS '직급 코드',
	j.job_name AS '직급명'
FROM employee e
INNER JOIN job j ON e.job_code = j.job_code;

방법 2


<ex2-4>
-- 각 사원들의 사번, 직원명, 직급 코드, 직급명을 조회
-- NATURAL JOIN : 동일한 컬럼명을 가지고 알아서 JOIN
-- 방법3) NATURAL JOIN > 하지만 잘 사용하지 않음

SELECT emp_id,
	emp_name,
	job_code,
	job_name
FROM employee
NATURAL JOIN job;

<ex2-4>


<ex3>
-- join 조건을 where 절에서도 사용이 가능
-- 하지만 join 조건은 INNER JOIN에, 검색 조건은 WHERE절에 기입하는걸 추천

SELECT e.emp_id,
	e.emp_name,
	j.*
FROM employee e
INNER JOIN job j
WHERE e.job_code = j.job_code;

<ex3>

더보기
#1
SELECT *
FROM employee e;

#2
SELECT *
FROM employee e
INNER JOIN department d ON e.dept_code = d.dept_id;
#1
#2

 

- #1의 실행결과는 23행이 조회되고 #2는 21행이 조회된다. 이유는 JOIN 조건에서 조건값이 NULL값인 행들은 JOIN이 되지 않기때문이다.

 

3. 외부 조인(OUTER JOIN)

  • 외부 조인(OUTER JOIN)은 조인의 조건에 만족되지 않는 행까지도 조회하기 위해서 사용되는 조인
  • LEFT OUTER JOIN은 왼쪽 테이블의 데이터는 모두 조회하려고 할 때 사용
SELECT *
FROM employees e
LEFT OUTER JOIN departments d ON e.dept_no = d.dept_no;
#1
-- OUTER JOIN과 비교할 INNER JOIN 구문
-- 부서가 지정되지 않은 사원 2명에 대한 정보가 조회되지 않음
-- 부서가 지정되어 있어도 부서에 속해있는 사원이 없으면 
-- 부서에 대한 정보가 조회되지 않는다.
SELECT e.emp_name,
	d.dept_title,
	e.dept_code,
	e.salary
FROM employee e
INNER JOIN department d ON e.dept_code = d.dept_id
ORDER BY e.dept_code;


#2 LEFT OUTER JOIN
-- employee테이블을 기준으로 조인
-- JOIN 조건에 부합되지 않아도 employee테이블은 모두 나옴
-- 부서 코드가 없던 사원의 정보가 출력된다.
SELECT e.emp_name,
	d.dept_title,
	e.dept_code,
	e.salary
FROM employee e
LEFT OUTER JOIN department d ON e.dept_code = d.dept_id
ORDER BY e.dept_code;

#1 부서가 지정되지 않은 사원의 정보는 조회되지 않음
#2 부서가 지정되지 않은 사원의 정보도 조회가 가능


  • RIGHT OUTER JOIN은 오른쪽 테이블의 데이터는 모두 조회하려고 할 때 사용
SELECT *
FROM employees e
RIGHT OUTER JOIN departments d ON e.dept_no = d.dept_no;
#1
-- OUTER JOIN과 비교할 INNER JOIN 구문
-- 부서가 지정되지 않은 사원 2명에 대한 정보가 조회되지 않음
-- 부서가 지정되어 있어도 부서에 속해있는 사원이 없으면 
-- 부서에 대한 정보가 조회되지 않는다.
SELECT e.emp_name,
	d.dept_title,
	e.dept_code,
	e.salary
FROM employee e
INNER JOIN department d ON e.dept_code = d.dept_id
ORDER BY e.dept_code;


#2 RIGHT OUTER JOIN
-- 부서에 속해있는 사원이 없어도 부서에 대한 정보가 출력된다.

SELECT e.emp_name,
	d.dept_title,
	e.dept_code,
	e.salary
FROM employee e
RIGHT OUTER JOIN department d ON e.dept_code = d.dept_id
ORDER BY e.dept_code;

#1 부서가 지정되지 않은 사원의 정보는 조회되지 않음
#2 부서에 속해있는 사원이 없어도 부서에 대한 정보가 출력

 

4. 상호 조인(CROSS JOIN)

  • 상호 조인(CROSS JOIN)은 한쪽 테이블의 모든 행들과 다른 쪽 테이블의 모든 행을 조인
    • 거의 사용되지 않음
SELECT *
FROM employees e
CROSS JOIN departments d;
-- CROSS JOIN 실습
# 3개의 행을 가지고 있는 테이블A와 
# 3개의 행을 가지고 있는 테이블B를 CROSS JOIN을 하면
# 총 9개의 행이 나옴
# 즉, 테이블A 행 개수 * 테이블B 행 개수

# employee 테이블은 23행이고
# department 테이블은 9행이므로
# 207행이 출력
SELECT e.emp_name,
	d.dept_title
FROM employee e
CROSS JOIN department d
ORDER BY e.emp_name;

CROSS JOIN 결과 207행이 출

 

5. 자체 조인(SELF JOIN)

  • 자체 조인(SELF JOIN)은 동일한 테이블을 가지고 조인하여 데이터를 조회
    • 자기 자신과 JOIN
    • 테이블 별칭을 각각 다르게 부여하여 두개의 테이블을 구별하여 JOIN
SELECT *
FROM employees e
INNER JOIN employees M ON e.manager_no = m.emp_no;

 

<ex1>
-- SELF JOIN

#1
# manager_id = 사수의  emp_id
SELECT *
FROM employee;

-- employee 테이블을 SELF JOIN하여 사번, 사원 이름, 부서 코드,
-- 사수 사번, 사수 이름 조회
#2

SELECT e.emp_id AS '사번',
	e.emp_name AS '사원명',
	e.dept_code AS '부서코드',
	m.emp_id AS '사수 사번',		-- e.manager_id와 동일
	m.emp_name AS '사수명'
FROM employee e
INNER JOIN employee m ON e.manager_id = m.emp_id
;

#1 emp_id 와 manager_id 를 조건으로 JOIN할 것임
#2 R: 직원정보 B: 사수정보


<ex2>
-- 사수가 없는 사원의 정보도 출력할 수 있도록
-- LEFT OUTER JOIN과 SELF JOIN 함께 사용

SELECT e.emp_id AS '사번',
	e.emp_name AS '사원명',
	e.dept_code AS '부서코드',
	m.emp_id AS '사수 사번',
	m.emp_name AS '사수명'
FROM employee e
LEFT OUTER JOIN employee m ON e.manager_id = m.emp_id
;

사수가 없는 사원의 정보도 LEFT OUTER JOIN을 사용하여 조회

 

6. UNION/UNION ALL 연산자

  • UNION 연산자는 두 쿼리의 결과를 하나로 합치는 연산자
    • 쿼리 A에서 2개의 행, 쿼리 B에서 3개의 행이 조회되면 총 5개의 행을 출력
    • 두개의 쿼리문의 SELECT 절에서 사용한 컬럼의 개수가 동일하지 않으면 오류발생
  • UNION 연산자는 중복된 열은 제거되고 데이터가 정렬되어 조회
  • UNION ALL 연산자는 UNION 연산자와 다르게 중복된 열까지 모두 출력
SELECT *
FROM employees
WHERE gender = '남자'

UNION -- 또는 UNION ALL

SELECT *
FROM employees
WHERE salary > 3000000;
#0 UNION 연산자에 사용할 쿼리문

#0-1
-- employee 테이블에서 부서 코드가 D5인 사원들의 사번, 직원명, 부서코드,
-- 급여를 조회
SELECT emp_id AS '사번',
	emp_name AS '직원명',
	dept_code AS '부서코드',
	salary AS '급여'
FROM employee
WHERE dept_code = 'D5'
;

#0-2
-- employee 테이블에서 급여가 300만원 초과인 사원들의 사번, 직원명,
-- 부서 코드, 급여를 조회
SELECT emp_id AS '사번',
	emp_name AS '직원명',
	dept_code AS '부서코드',
	salary AS '급여'
FROM employee
WHERE salary > 3000000
;

# 0-1
# 0-2


#1 UNION 연산자
<ex 1>
SELECT emp_id AS '사번',
	emp_name AS '직원명',
	dept_code AS '부서코드',
	salary AS '급여'
FROM employee
WHERE dept_code = 'D5'


UNION

SELECT emp_id AS '사번',
	emp_name AS '직원명',
	dept_code AS '부서코드',
	salary AS '급여'
FROM employee
WHERE salary > 3000000
;


-- WHERE 절로 변경
-- UNION 연산자를 사용하여 조회한 것과 결과 동일
SELECT emp_id AS '사번',
	emp_name AS '직원명',
	dept_code AS '부서코드',
	salary AS '급여'
FROM employee
WHERE dept_code = 'D5' OR salary > 3000000

사번 209, 215인 정보는 두 쿼리문에 모두 동일하게 조회되기 때문에 중복은 제거하고 출


#2 UNION ALL
SELECT emp_id AS '사번',
	emp_name AS '직원명',
	dept_code AS '부서코드',
	salary AS '급여'
FROM employee
WHERE dept_code = 'D5'

UNION

SELECT emp_id AS '사번',
	emp_name AS '직원명',
	dept_code AS '부서코드',
	salary AS '급여'
FROM employee
WHERE salary > 3000000
;

#2 UNION ALL은 중복된 값도 제거하지 않고 출력

 

서브쿼리(SubQuery )


1. 서브쿼리(SubQuery)

  • 하나의  SQL문 안에 포함된 또 다른 SQL 문
-- 서브 쿼리 실습

#1. 노옹철 사원과 같은 부서원들을 조회

#1-1 노옹철 사원의 부서를 조회
SELECT emp_name, 
	dept_code
FROM employee
WHERE emp_name = '노옹철';


#1-2 부서 코드가 노옹철 사원의 부서 코드와 동일한 사원들을 조회
SELECT emp_name, 
	dept_code
FROM employee
WHERE dept_code = 'D9';


#1-3 위의 2단계를 서브 쿼리를 사용하여 하나의 쿼리문을 ㅗ작성
SELECT emp_name, 
	dept_code
FROM employee
WHERE dept_code = (
	SELECT dept_code
	FROM employee
	WHERE emp_name = '노옹철'
);

#1-1

 

#1-2
#1-3


#2
-- 전 직원의 평균 급여보다 더 많은 급여를 받고 있는 직원들의 사번, 
-- 직원명, 직급 코드, 급여를 조회
#2-1 전 직원의 평균 급여 조회
SELECT FLOOR(AVG(salary))
FROM employee
;

#2-2 평균 급여보다 더 많은 급여를 받고 있는 직원들을 조회
SELECT emp_id AS '사번',
	emp_name AS '사원명',
	job_code AS '직급 코드',
	salary AS '급여'
FROM employee
WHERE salary > 3047662
;

#2-3 위의 2단계를 서브 쿼리를 사용하여 하나의 쿼리문으로 작성
SELECT emp_id AS '사번',
	emp_name AS '사원명',
	job_code AS '직급 코드',
	salary AS '급여'
FROM employee
WHERE salary > (
	SELECT FLOOR(AVG(salary))
	FROM employee
);

#2-1
#2-2
#2-3

2. 서브 쿼리 구분

  • 서브 쿼리는 서브 쿼리를 수행한 결과값의 행과 열의 개수에 따라서 분류 가능
  • 단일행 서브쿼리 : 서브 쿼리의 조회 결과 값의 개수가 1개일 경우
#1
-- 노옹철 사원의 급여보다 더 많이 받는 사원의 사번, 직원명,
-- 부서명, 급여 조회

#1-1 노옹철 사원의 급여
SELECT salary
FROM employee
WHERE emp_name = '노옹철'
;

#1-2 노옹철 사원의 급여보다 더 ㅁ낳이 받는 사원을 조회
SELECT e.emp_id AS '사번',
	e.emp_name AS '사원명',
	d.dept_title AS '부서명',
	e.salary AS '급여'
FROM employee e
INNER JOIN department d ON e.dept_code = d.dept_id
WHERE salary > 3700000
;


#1-3 서브쿼리를 활용하여 #1-1과 #1-2를 취합
SELECT e.emp_id AS '사번',
	e.emp_name AS '사원명',
	d.dept_title AS '부서명',
	e.salary AS '급여'
FROM employee e
INNER JOIN department d ON e.dept_code = d.dept_id
WHERE salary > (
	SELECT salary
	FROM employee
	WHERE emp_name = '노옹철'
)
;

#1-1
#1-2
#1-3


  • 다중행 서브쿼리 : 서브 쿼리의 조회 결과 값의 개수가 여러 행일 경우
    • 다중행 서브쿼리는 조회 결과값이 여러개이기 때문에 단순비교 연산자를 사용 불가능(에러 발생)
    • ANY  연산자
    • ALL 연산자
#1
-- 각 부서별 최고 급여를 받는 직원의 이름, 직급 코드, 부서코드, 급여 조회

#1
-- 각 부서별 최고 급여를 받는 직원의 이름, 직급 코드, 부서코드, 급여 조회

#1-1 부서별 최고 급여 조회
SELECT MAX(salary) AS '해당 부서의 최고 급여'
FROM employee
GROUP BY dept_code
;


#1-2 위 급여를 받는 사원들을 조회
SELECT emp_name AS '사원명',
	job_code AS '직급코드',
	dept_code AS '부서 코드',
	salary AS '급여'
FROM employee
WHERE salary IN (2890000, 3660000, 2490000, 3760000, 3900000, 2550000, 8000000)
ORDER BY dept_code
;


#1-3 #1-1과 #1-2를 서브쿼리를 사용하여 취합
SELECT emp_name AS '사원명',
	job_code AS '직급코드',
	dept_code AS '부서 코드',
	salary AS '급여'
FROM employee
WHERE salary IN (
	SELECT MAX(salary) AS '해당 부서의 최고 급여'
	FROM employee
	GROUP BY dept_code
)
ORDER BY dept_code
;

#1-1
#1-2
#1-3


#2
-- 직원에 대해 사번, 이름, 부서코드, 구분(사원/사수) 조회

#2-1 사수에 해당하는 사번을 조회
SELECT DISTINCT manager_id AS '사수번호'
FROM employee
WHERE manager_id IS NOT NULL
;


#2-2 사수/ 사원을 구분하여 조회
SELECT emp_id AS '사번',
	emp_name AS '사원명',
	dept_code AS '부서코드',
	CASE WHEN emp_id IN (200, 201, 204, 207, 211, 214,100) THEN '사수'
		ELSE '사원'
	END AS '구분'
FROM employee
;

#2-3 SELECT 절에 서브 쿼리를 사용
SELECT emp_id AS '사번',
	emp_name AS '사원명',
	dept_code AS '부서코드',
	CASE WHEN emp_id IN (
		SELECT DISTINCT manager_id AS '사수번호'
		FROM employee
		WHERE manager_id IS NOT NULL
		) THEN '사수'
		ELSE '사원'
	END AS '구분'
FROM employee
;

#2-1
#2-2
#2-3 #2-2와 결과 동일


  • ANY 연산자는 서브쿼리의 결과 중 하나라도 조건을 만족하면 TRUE를 반환 
#1
-- 대리 직금임에도 과장 직급들의 최소 급여보다
-- 많이 맏는 직원의 사번, 이름, 직급코드, 급여 조회


#1-1 과장 직급들의 급여 조회
SELECT salary AS '급여'
FROM employee
WHERE job_code = 'J5'
;



#1-2 WHERE 절에 ANY를 이용하여 서브 쿼리를 사용
SELECT emp_id AS '사번',
	emp_name AS '이름',
	job_code AS '직급코드',
	salary AS '급여'
FROM employee
WHERE job_code = 'J6' AND 
	-- AND salary > 2200만 OR salary > 250만 OR salary > 376만 과 동일
    salary > ANY (
		SELECT salary AS '급여'
		FROM employee
		WHERE job_code = 'J5'
)
;

#1-1
#1-2


  • ALL 연산자는  서브쿼리의 결과 모두가 조건을 만족하면 TRUE를 반환한다.
    • = 기호는 논리적 오류가 있으므로 사용이 불가
#1
-- 과장 직급임에도 차장 직급의 최대 급여보다 더 많이 받는ㄴ
-- 직원들의 사번, 이름, 직급, 급여 조회

#1-1 차장 직급들의 급여 조회
SELECT salary
FROM employee e
INNER JOIN job j ON e.job_code = j.job_code
WHERE j.job_name = '차장'
;


#1-2 WHERE 절에 ANY를 이용하여 서브 쿼리를 사용
SELECT e.emp_id AS '사번',
	e.emp_name AS '사원명',
	j.job_name AS '직급명',
	e.salary AS '급여'
FROM employee e
INNER JOIN job j ON e.job_code = j.job_code
WHERE j.job_name = '과장'
	AND salary > ALL (			-- salary > 280만 AND salary > 155만 AND salary > 249만 AND salary > 248만
		SELECT salary
		FROM employee e
		INNER JOIN job j ON e.job_code = j.job_code
		WHERE j.job_name = '차장'
	)
;

#1-1
#1-2


  • 다중열 서브쿼리 : 서브 쿼리의 조회 결과 값은 한 행이지만 열의 수가 여러개일 경우
#1
-- 하이유 사원과 같은 부서코드, 직급 코드에 해당하는 사원들을 조회


#1-1 하이유 사원의 부서 코드와 직급 코드 조회
SELECT dept_code AS '부서코드',
	job_code AS '직급 코드'
FROM employee
WHERE emp_name = '하이유'
;


#1-2 부서 코드가 D5이면서 직급 코드가 J5인 사람들을 조회
SELECT emp_name AS '사원명',
	dept_code AS '부서코드',
	job_code AS '직급 코드'
FROM employee
WHERE dept_code = 'D5' AND job_code = 'J5'
;


#1-3 2개의 서브 쿼리를 사용하여 부서 코드가 D5이면서 직급 코드가 J5인 사람들을 조회
SELECT emp_name AS '사원명',
	dept_code AS '부서코드',
	job_code AS '직급 코드'
FROM employee
WHERE dept_code = (
	SELECT dept_code
	FROM employee
	WHERE emp_name = '하이유'
	) 
	AND job_code = (
		SELECT job_code
		FROM employee
		WHERE emp_name = '하이유'
)
;

#1-4 1개의 서브 쿼리를 사용하여 부서 코드가 D5이면서 직급 코드가 J5인 사람들을 조회
# 쌍 비교 방식 : (,) = (,)형식으로 여러개의 컬럼을 동시에 비교
SELECT emp_name AS '사원명',
	dept_code AS '부서코드',
	job_code AS '직급 코드'
FROM employee
WHERE (dept_code, job_code) = (				
				SELECT dept_code AS '부서코드',
						job_code AS '직급 코드'
				FROM employee
				WHERE emp_name = '하이유'
				)
;

#1-1
#1-2
#1-3
#1-4


#2
-- 박나라 사원과 직급 코드가 일치하면서 같은 사수를 가지고 있는
-- 사원의 사번, 이름, 직급 코드, 사수 사번 조회

#2-1 박나라 사원의 직급 코드와 사수의 사번을 조회
SELECT job_code AS '직급 코드',
	manager_id AS '사수 사번'
FROM employee
WHERE emp_name = '박나라'
;

#2-2 서브쿼리사용하여 작성
SELECT emp_id AS '사번',
	emp_name AS '사원명',
	job_code AS '직급 코드',
	manager_id AS '사수 사번'
FROM employee
WHERE (job_code, manager_id) = (
				SELECT job_code,
					manager_id
				FROM employee
				WHERE emp_name = '박나라'
				)
;

#2-1
#2-2


  • 다중행 다중열 서브쿼리 : 서브 쿼리의 조회 결과값이 여러 행, 여러 열일 경우
#1
-- 각 부서별 최고 급여를 받는 직원의 사번, 이름, 직급 코드, 부서코드, 급여 조회

#1-1 부서별 최고 급여 조회
SELECT dept_code AS '부서코드',
	MAX(salary) AS '최고급여'
FROM employee
GROUP BY dept_code;


#1-2 각 부서별 최고 급여를 받는 직원들의 정보 조회
# 비효울적
SELECT emp_id AS '사번',
	emp_name AS '사원명',
	job_code AS '직급코드',
	dept_code AS '부서코드',
	salary AS '급여'
FROM employee
WHERE dept_code = 'D1' AND salary = 3660000
	OR dept_code = 'D2' AND salary = 2490000
	OR dept_code = 'D5' AND salary = 3760000
	OR dept_code = 'D6' AND salary = 3900000
	OR dept_code = 'D8' AND salary = 2550000
	OR dept_code = 'D9' AND salary = 8000000
	OR dept_code IS NULL AND salary = 2890000
;

#1-3 다중행, 다중열 서브쿼리를 사용하여 각 부서별 최고 급여를 받는 직원들의 정보 조회
SELECT emp_id AS '사번',
	emp_name AS '사원명',
	job_code AS '직급코드',
	IFNULL(dept_code, '부서없음') AS '부서코드',
	salary AS '급여'
FROM employee
WHERE ( IFNULL(dept_code, '부서없음'), salary) IN (
				SELECT IFNULL(dept_code, '부서없음'),
					MAX(salary)
				FROM employee
				GROUP BY dept_code
				)
ORDER BY dept_code
;

#1-1
#1-2
#1-3

 


  • 인라인 뷰 : FROM절에 서브 쿼리를 제시하고, 서브 쿼리를 수행한 결과를 테이블 대신에 사용
#1
SELECT emp_id AS '사번',
	emp_name AS '사원명',
	salary AS '급여',
	salary * 12 AS '연봉'
FROM employee
;


SELECT e.사번,
	e.사원명,
	e.급여,
	e.연봉
FROM (
	SELECT emp_id AS '사번',
		emp_name AS '사원명',
		salary AS '급여',
		salary * 12 AS '연봉'
	FROM employee
)e;

#1 결과


-- employee 테이블에서 급여로 순위를 사원의 정보 출력

#2-1 employee 테이블에서 급여로 순위를 매겨서 출력
SELECT ROW_NUMBER() OVER (ORDER BY salary DESC) AS '순위',  
	emp_name AS '사원명',
	salary AS '급여'
FROM employee
;

#2-2 서브쿼리(인라인 뷰)를 사용하여 급여 순위 5위인 사원의 정보 출력
SELECT e.순위,
	e.사원명,
	e.급여
FROM (
	SELECT ROW_NUMBER() OVER (ORDER BY salary DESC) AS '순위',  
		emp_name AS '사원명',
		salary AS '급여'
	FROM employee
	)e
WHERE e.순위 = 5
;


#2-3 서브쿼리(인라인 뷰)를 사용하여 급여 순위 5위에서 10위인 사원의 정보 출력
SELECT e.순위,
	e.사원명,
	e.급여
FROM (
	SELECT ROW_NUMBER() OVER (ORDER BY salary DESC) AS '순위',  
		emp_name AS '사원명',
		salary AS '급여'
	FROM employee
	)e
WHERE e.순위 BETWEEN 5 AND 10
;

#2-1
#2-2
#2-3

'Database' 카테고리의 다른 글

[Database] 뷰(View)  (0) 2024.05.23
[Database] DB 모델링  (0) 2024.05.22
[Database] 데이터 형식(Data Type) & 함수(2)  (0) 2024.05.20
[Database] 데이터 형식(Data Type) & 함수 (1)  (0) 2024.05.17
[Database] SQL 기본 (2)  (0) 2024.05.17

실습 문제

Q1. 아래의 쿼리가 정상적으로 연산되도록 쿼리문을 작성하시오.

잘못된 결과 값

더보기

 

-- 아래의 쿼리가 정상적으로 연산되도록 쿼리문을 작성하시오.
SELECT '1,000,000' - '500,000'
-- 명시적 형변환
#1
SELECT CONVERT(REPLACE('1,000,000', ',', ''), INT) - CONVERT(REPLACE('500,000', ',', ''), INT)
#2
SELECT REPLACE('1,000,000', ',', '') - REPLACE('500,000', ',', '')

-- 묵시적 형변환
-- ,(콤마)를 제거하면 -연산자로 인해 값 그대로 형변환 가능
#3
SELECT '1000000' - '500000'
#1
#2
#3

 

Q2. employee 테이블에서 emp_id를 숫자 형식으로 변환해서 조회

더보기
-- employee 테이블에서 emp_id를 숫자 형식으로 변환해서 조회
SELECT CONVERT(emp_id, INT),
	emp_name
FROM employee;

데이터 형식(Data Type)

 

함수


3. 문자열 함수

-- CONCAT(), CONCAT_WS()

# CONCAT() 함수
SELECT CONCAT('2024', '05', '20');

# CONCAT_WS() 함수
SELECT CONCAT_WS('/', '2024', '05', '20');

CONCAT() 함수
CONCAT_WS() 함


<ex1>
-- usertbl 테이블에서 아이디, 이름, 전화번호를 조회

SELECT userID AS "아이디",
	NAME AS "이름",
	CONCAT( mobile1, mobile2) AS 전화번호
FROM usertbl;

mobile1 과 mobile2를 CONCAT() 함수를 사용하여 이어줌


<ex2>
-- employee 테이블에서 급여 조회

SELECT CONCAT(emp_name, '님의 급여는 ', salary, '입니다.') AS "급여"
FROM employee;

CONCAT() 함수를 통해 조회결과를 문장으로 출력


-- ELT(), FIELD(), FIND_IN_SET(), INSTR(), LOCATE() 함수

# ELT() : 위치번째에 해당하는 문자열을 반환
# 2가 입력되었기 때문에 2에 해당하는 '둘'을 반환
SELECT ELT(2, '하나', '둘', '셋');

# FIELD() : 찾을 문자열의 위치를 찾아서 반환
# '둘' 에 해당하는 문자열이 2번째에 있기 때문에 2를 반환
SELECT FIELD('둘', '하나', '둘', '셋');

# FIND_IN_SET() : 찾을 문자얼의 위치를 찾아서 반환
# 하나의 문자열을 ,(콤마)로 구분하여 찾음
# '둘' 에 해당하는 문자열이 ,(콤마)를 기준으로 2번째에 있기 때문에
# 2 를 반환
SELECT FIND_IN_SET('둘', '하나,둘,셋');


# INSTR() : 기준 문자열에서 부분 문자열을 찾아서 그 시작 위치를 반환
# '둘'이 시작위치가 3번째이기 때문에 3을 반환
SELECT INSTR('하나둘셋', '둘');

# LOCATE() : INSTR()과 순서만 다르고 결과가 동일
# '둘'이 시작위치가 3번째이기 때문에 3을 반환
SELECT LOCATE('둘', '하나둘셋');

ELT() 함수 결과
FIELD() 함수 결과
FIND_IN_SET() 함수 결과
INSTR() 함수 결과
LOCATE() 함수 결과


<ex1>
-- employee 테이블에서 이메일의 @ 위치값 출력

SELECT email,
	INSTR(email, '@')
FROM employee;

@ 문자의 위치를 찾아 위치값 출력



-- INSERT() 함수
# INSERT('기준 문자열', 삽입 시작 위치, 삭제될 문자 개수, '삽입할 문자')

#1 : 문자 4개 삭제
SELECT INSERT('ABCEDFGHI', 3, 4, '@@@@');

#2 : 문자 2개 삭제
SELECT INSERT('ABCEDFGHI', 3, 2, '@@@@');

#1
#2


<ex1>
-- employee 테이블에서 사원명, 주민등록번호 조회

SELECT emp_name AS "이름",
	INSERT(emp_no, 9, 6, '******') AS "주민등록번호"
FROM employee;

주민등록번호를 앞자리 6 자리와 성별을 제외하고 가려서 출력


-- LEFT(), RIGHT() 함수

# LEFT() : 기준문자열를 왼쪽에서 3개 잘라내어 출력
SELECT LEFT('ABCEDFGHI', 3);

# RIGHT() : 기준문자열를 오른쪽에서 3개 잘라내어 출력
SELECT RIGHT('ABCEDFGHI', 3);

LEFT() 함수 결과
RIGHT() 함수 결과


<ex1>
-- employee 테이블에서 사원명, email의 ID만을 출력

SELECT emp_name,
	LEFT(email, INSTR(email, '@')-1) AS 'ID'
FROM employee;

INSTR() 함수로 @ 기호의 위치값을 얻어 LEFT() 함수를 통해 ID만을 출력


-- UPPER(), LOWER() 함수

# UPPER() : 소문자를 모두 대문자를 변환
SELECT UPPER('abcDEF');

# LOWER() : 대문자를 모두 소문자를 변환
SELECT LOWER('abcDEF');

UPPER() 함수 결과
LOWER() 함수 결과


 

-- LPAD(), RPAD() 함수

# LPAD() : 왼쪽에 남은 문자열 수 넣음
# 문자열을 넣어주지 않으면 공백
SELECT LPAD('HELLO', 10), LPAD('HELLO', 10, '#');

# RPAD() : 오른쪽에 남은 문자열 수 넣음
# 문자열을 넣어주지 않으면 공백
SELECT RPAD('HELLO', 10), RPAD('HELLO', 10, '#');

LPAD() 함수 결
RPAD() 함수 결과


<ex1>
-- employee 테이블에서 사원명, 주민등록번호 출력

SELECT emp_name,
 RPAD(LEFT(emp_no, 8), 14, '*') AS "주민등록번호"
FROM employee;

LPAD()와 RPAD()를 중첩하여 사용


-- LTRIM(), RTRIM(), TRIM() 함수 사용

# LTRIM(): 왼쪽 공백만 제거
SELECT LTRIM('     HELLO     ');

# RTRIM(): 오른쪽 공백만 제거
SELECT RTRIM('     HELLO     ');

# TRIM(): 양쪽 공백만 제거
SELECT TRIM('     HELLO     ');

LTRIM() 함수 결과
RTRIM() 함수 결과
TRIM() 함수 결과

 


-- TRIM(방향 자를 문자열 FROM 문자열)

#1
# 양쪽 공백을 모두 지움
SELECT TRIM(BOTH ' ' FROM '     HELLO     ');

#2
# 양쪽 'Z'문자를 모두 지움
SELECT TRIM(BOTH 'Z' FROM 'ZZZZZHELLOZZZZZ');

#3
# 중간에 삽입된 'Z'는 지워지지 않음
SELECT TRIM(BOTH 'Z' FROM 'ZZZZZHEZLLOZZZZZ');

#4
# 왼쪽에 삽입된 'Z'만 지움
SELECT TRIM(LEADING 'Z' FROM 'ZZZZZHEZLLOZZZZZ');

#5
# 오른쪽에 삽입된 'Z'만 지움
SELECT TRIM(TRAILING 'Z' FROM 'ZZZZZHEZLLOZZZZZ');

#1
#2
#3
#4
#5


-- REPEAT(), SPACE() 함수
# REPEAT() : 특정문자열 N번 반복
# SPACE() : 공백을 N칸 넣음

SELECT REPEAT('HELLO', 3), SPACE(10);

REPEAT()함수와 SPACE()함수 결과


-- REVERSE() 함수

# REVERSE() : 문자열을 뒤집어서 출력
SELECT REVERSE("HELLO");

REVERSE() 함수 결과


-- REPLACE() 함수
# Replace('문자열', '원래 문자열', '바꿀 문자열')

SELECT REPLACE('hong123@naver.com', 'naver.com', 'gmail.com');


<ex1>
-- employee 테이블에서 이메일의 kh.or.kr을 naver.com 변경해서 조회

SELECT emp_name AS "사원명",
	REPLACE(email, "kh.or.kr", "naver.com")
FROM employee;

REPLACE() 함수를통해 이메일 변경


<ex2>
-- employee 테이블에서 이메일의 아이디만을 조회

SELECT emp_name AS "사원명",
	REPLACE(email, "@kh.or.kr", "") AS "아이디"
FROM employee;

REPLACE() 함수를 통해 아이디만을 출력


-- SUBSTRING() 함수

#1
# SUBSTRING(문자열, 시작위치, 길이)
SELECT SUBSTRING('대한민국 만세', 3, 2);

#2
# SUBSTRING(문자열, 시작위치) : 시작위치만 입력하면 끝까지
SELECT SUBSTRING('대한민국 만세', 3);

#3
# 음수값은 뒤에서부터를 의미
SELECT SUBSTRING('대한민국 만세', -2, 2);

#1
#2
#3


<ex1>
-- employee 테이블에서 이름, 아이디,  성별 조회
SELECT emp_name,
	SUBSTRING(email, 1, INSTR(email, '@')-1) AS '아이디',
	IF(SUBSTRING(emp_no, 8, 1) = 1, '남자', '여자') AS '성별'
FROM employee;

SUBSTRING() 함수를 통해 ID 출력, 주민등록번호로 성별 출력


-- SUBSTRING_INDEX() 함수

#1
# 양수 : 왼쪽에서 부터 첫번째 구분자를 찾고 오른쪽 부분을 삭제
SELECT SUBSTRING_INDEX('cafe.naver.com', '.', 1);

#2
# 음수 : 오른쪽에서 부터 첫번째 구분자를 찾고 왼쪽 부분을 삭제
SELECT SUBSTRING_INDEX('cafe.naver.com', '.', -1);

#1
#2


<ex1>
-- employee 테이블에서 아이디 조회

SELECT emp_name AS '사원명',
	SUBSTRING_INDEX(email, '@', 1) AS '아이디'
FROM employee;

SUBSTRING_INDEX() 함수를 통해 아이디를 조회

 

4. 수학 함수

 

-- ABS() 함수: 절대값 출력 함수
SELECT ABS(100), ABS(-100),
	ABS(10.9), ABS(-10.9);

ABS() 함수 결과


-- CEILING(), FLOOR(), ROUND(), TRUNCATE() 함수

# CEILING() : 올림 함수
SELECT CEILING(4.3);

# FLOOR() : 내림 함수
SELECT FLOOR(4.7);

# ROUND(x) : ROUND(X, 0)과 동일
SELECT ROUND(4.355), ROUND(4.355, 0);

# ROUND(x, D) : 소수점 D자리까지 반올림
# D 양수 : 소수점 기준
# D 음수 : 자연수 기준
SELECT ROUND(4.355, 2), ROUND(14.355, -1);

# TRUNCATE() : 소수점 기준으로 정수 위치까지 구하고 나머지를 삭제
SELECT TRUNCATE(123.456, 0), TRUNCATE(123.456, 1);

CEILING() 함수 결
FLOOR() 함수 결과
ROUND(X) 함수 결과
ROUND(X, D) 함수결과
TRUNCATE()함수 결과


-- MOD() 함수
# MOD(숫자1, 숫자2) : 나머지 함수
# 숫자1을 숫자2로 나눈 나머지값을 반환

SELECT MOD(157, 10) , 157 % 10, 157 MOD 10;

3개의 결과값이 모두 동일


-- RAND() 함수
#1
# RAND() : 0<=X<=1 범위의 값이 랜덤으로 출력
SELECT RAND(), RAND(), RAND();

#2
# RAND() 함수 범위지정
SELECT RAND() * 100 			-- 0.0 ~ 99.99999
	FLOOR(RAND() * 100), 		-- 0 ~99
	FLOOR(RAND() * 100) +1 ; 	-- 1 ~ 100

#1
#2


-- POW(), SQRT(), SIGN() 함수

# POW() : 거듭 제곱 함수
SELECT POW(2,3);

# SQRT() : 제곱근 함수
SELECT SQRT(9);

# SIGN() : 양수, 0, 음수 판별하는 함수
SELECT SIGN(100), SIGN(0), SIGN(-100);

POW() 함수 결
SQRT() 함수 결
SIGN() 함수 결과

 

5. 날짜 및 시간 함수

-- ADDDATE(), SUBDATE()함수

#1
# ADDDATE() : 날짜 더하는 함수
SELECT ADDDATE('2024-05-20', INTERVAL 31 DAY),	-- 31일 더하기
	ADDDATE('2024-05-20', INTERVAL 1 MONTH),	-- 한달 더하기
	ADDDATE('2024-05-20', INTERVAL 1 YEAR);		-- 1년 더하기
	
#2
# SUBDATE() : 날짜를 빼는 함수
SELECT SUBDATE('2024-05-20', INTERVAL 31 DAY),	-- 31일 빼기
	SUBDATE('2024-05-20', INTERVAL 1 MONTH),	-- 한달 빼기
	SUBDATE('2024-05-20', INTERVAL 1 YEAR)		-- 1년 빼기

#1
#2


#1
# ADDTIME() : 시간을 더하는 함수
SELECT ADDTIME('2024-05-20 09:00:00', '01:10:30'), -- 1시간 10분 30초 더하기
	ADDTIME('09:00:00', '02:20:50');						-- 2시간 20분 50초 더하기

#2
# ADDTIME() : 시간을 더하는 함수
SELECT SUBTIME('2024-05-20 09:00:00', '01:10:30'), -- 1시간 10분 30초 빼기
	SUBTIME('09:00:00', '02:20:50');						-- 2시간 20분 50초 빼기

#1
#2


<ex1>
-- employee테이블에서 사원명, 입사일, 인턴(3개월) 종료일 구하기

SELECT emp_name AS '사원명',
	hire_date AS '입사일',
	ADDDATE(hire_date, INTERVAL 3 MONTH) AS '인턴 종료일'
FROM employee;

ADDDATE()함수를 통해 인턴종료일 출력


-- CURDATE(), CURTIME(), NOW(), SYSDATE() 함수

SELECT CURDATE(),		-- 현재 날짜
	CURTIME(),		-- 현재 시간
	NOW(),			-- 현재 날짜와 시간
	SYSDATE();		-- 현재 날짜와 시간

CURDATE(), CURTIME(), NOW(), SYSDATE() 함수 결과


#1	
-- YEAR(), MONTH(), DAY() 함수 : DATE 타입을 입력 받음
SELECT YEAR(CURDATE()),		-- 년을 출력
	MONTH(CURDATE()),	-- 월을 출력
	DAY(CURDATE());		-- 일을 출력

#2
-- HOUR(), MINUTE(), SECOND() : TIME 타입을 입력받음
SELECT HOUR(CURTIME()),		-- 시간을 출력
	MINUTE(CURTIME()),	-- 분을 출력
	SECOND(CURTIME());	-- 초를 출력

#1
#2


-- DATEDIFF(), TIMEDIFF() 함수
#1
#DATEDIFF(날짜1, 날짜2) : 날짜 1에서 날짜 2를 뺌 
SELECT DATEDIFF('2022-05-20', CURDATE()),
	DATEDIFF(CURDATE(), '2022-05-20');

#2
# TIMEDIFF(시간1, 시간2) : 시간 1에서 시간 2를 뺌 
SELECT TIMEDIFF('09:00:00', CURTIME()),
	TIMEDIFF(CURTIME(), '09:00:00');

#1
#2


<ex1>
-- employee 테이블에서 직원명, 입사일, 근무 일수 조회

SELECT emp_name AS '직원명',
	hire_date AS '입사일' ,
	DATEDIFF(CURDATE(), hire_date) AS '근무 일수'
FROM employee;

DATEDIFF()함수로 근무일수 조회


-- DAYOFWEEK(), MONTHNAME(), DAYOFYEAR(), LAST_DAY() 함수 : 날짜 데이터를 입력받음

#1
# DAYOFWEEK() : 날짜의 요일을 반환
# 1: 일요일, 2: 월요일, ..., 7: 토요일
SELECT DAYOFWEEK(CURDATE());

#2
# MONTHNAME() : 날짜의 월의 이름을 반환
SELECT MONTHNAME(CURDATE());

#3
# DAYOFYEAR() : 1년 중 몇 번째 날짜인지를 반환
SELECT DAYOFYEAR(CURDATE());

#4
# LAST_DAY() : 주어진 날짜의 달에 해당하는 마지막 날짜를 반환
SELECT LAST_DAY(CURDATE());

#1
#2
#3
#4


<ex1>
-- employee 테이블에서 직원명, 입사일, 급여일(매달 마지막 날) 조회

SELECT emp_name AS '직원명',
	hire_date AS '입사일',
	LAST_DAY(CURDATE()) AS '급여일'
FROM employee;

LAST_DAY() 함수를 통해 급여일 지정


-- MAKEDAY(), MAKETIME() 함수

#1
# MAKEDATE(연도, 정수) : 해당 '연도'에 '정수'만큼 지난 날짜를 반환
SELECT MAKEDATE(2024, 100);

#2 MAKETIME(시, 분, 초) : 입력값에 해당하는 시간을 반환
SELECT MAKETIME(22, 58, 25);

#1
#2


-- PERIOD_ADD(), PERIOD_DIFF(), QUARTER(), TIME_TO_SEC() 함수

#1
# PERIOD_ADD(연월, 개월 수) : 연월에서 개월만큼의 개월이 지난 연월을 반환
SELECT PERIOD_ADD(202405, 11);

#2
# PERIOD_DIFF(연월 1, 연월 2) : 연월 1 - 연월 2의 개울 수 반환
SELECT PERIOD_DIFF(202305, 202405);

#3
# QUARTER(날짜) : 날짜가 4분기 중 몇 분기에 해당하는지 반환
SELECT QUARTER(CURDATE());

#4
# TIME_TO_SEC(시간) : 시간을 초 단위로 반환
SELECT TIME_TO_SEC(CURTIME());

#1
#2
#3
#5

 

 

6. 시스템 정보 함수

 

7. 윈도우 함수

7.1. 순위 함수

  • 순위 윈도우 함수에는 ROW_NUMBER(), RANK(), DENSE_RANK(), NTILE() 등의 함수가 존재
  • 순위 윈도우 함수를 사용하면 데이터를 순서대로 번호 매기거나, 특정 조건에 따라 순위(등수)를 매길 수 있음
-- 윈도우 함수 "순위 함수"
-- ROW_NUMBER() 함수 : 순번을 매김

<ex1>
-- usertbl 테이블에서 키가 큰 순으로 순위를 매겨서 순위, 이름, 주소,
-- 키를 조회
# OVER절에 정렬 조건 기입

SELECT ROW_NUMBER() OVER(ORDER BY height DESC, NAME ASC) AS 'RANK', 
	NAME AS "이름",
	addr AS "주소",
	height AS "키"
FROM usertbl;


<ex2>
-- usertbl 테이블에서 지역별로 순위를 배겨서 주소 순위, 이름, 키 조회

SELECT addr AS '주소',
	ROW_NUMBER() OVER(PARTITION BY addr ORDER BY height DESC, NAME ASC) AS '주소별 순위',
	NAME AS '이름',
	height AS '키'
FROM usertbl
ORDER BY addr;

<ex1>
<ex2>


-- 윈도우 함수 "순위 함수"
# RANK() 함수 : 동일한 순위 이후의 등수를 동일한 인원수만큼 건너뛰고 증가


-- usertbl 테이블에서 키가 큰 순으로 순위를 매겨서 순위, 이름, 주소, 키를 조회
SELECT RANK() OVER(ORDER BY height DESC, NAME ASC) AS 'RANK', 
	NAME AS "이름",
	addr AS "주소",
	height AS "키"
FROM usertbl;

<ex1>


<ex2>
-- employee 급여가 높은 순서대로 순위 매겨서 순위, 직원명, 급여 조회

SELECT RANK() OVER(ORDER BY salary DESC, emp_name ASC) AS 'RANK',
	emp_name AS '직원명',
	salary AS '급여'
FROM employee;

<ex2>


-- 윈도우 함수 "순위 함수"
# DENSE_RANK() 함수 : 동일한 순위 이후의 등수를 1 증가

<ex1>
-- usertbl 테이블에서 키가 큰 순으로 순위를 매겨서 순위, 이름, 주소, 키를 조회
SELECT DENSE_RANK() OVER(ORDER BY height DESC, NAME ASC) AS 'RANK', 
	NAME AS "이름",
	addr AS "주소",
	height AS "키"
FROM usertbl;

<ex1>


-- 윈도우 함수 "순위 함수"
# NTILE(x) 함수 : 전체 인원을 어떠한 기준 순서로 세운 후에 x개의 그룹으로 분할

<ex1>
# usertbl 테이블에서 키가 순서로 세운 후에 3개의 그룹을 분할
SELECT NTILE(2) OVER(ORDER BY height DESC, NAME ASC) AS 'RANK', 
	NAME AS "이름",
	addr AS "주소",
	height AS "키"
FROM usertbl;

<ex1>


7.2. 분석 함수

  • 분석 윈도우 함수에는 LEAD(), LAG(), FIRST_VALUE(), LAST_VALUE(), CUME_DIST() 등의 함수가 존재
  • 분석 윈도우 함수를 사용하면 현재 행의 이전 행이나 다음 행의 데이터를 참조하거나, 윈도우의 첫 값이나 마지막 값을 가져올 수 있음
-- 윈도우 함수 "분석 함수"
# LEAD(column, n) : n 단위로 다음 등수의 데이터를 가져옴

<ex1>
-- usertbl 테이블에서 키 순서대로 정렬 후 다음 사람과 키 차이를 조회
SELECT NAME AS '직원명',
	addr AS '주소',
	height AS '키',
	height - LEAD(height, 1) OVER(ORDER BY height DESC) AS '다음 등수 키 차이'
FROM usertbl;

<ex1>


-- 윈도우 함수 "분석 함수"
# LAG(column, n) : n 단위로 이전 등수의 데이터를 가져옴

<ex1>
-- usertbl 테이블에서 키 순서대로 정렬 후 다음 사람과 키 차이를 조회
SELECT NAME AS '직원명',
	addr AS '주소',
	height AS '키',
	height - LAG(height, 1) OVER(ORDER BY height DESC) AS '이전 등수 키 차이'
FROM usertbl;

<ex1>

 


-- 윈도우 함수 "분석 함수"
# FIRT_VALUE(column) : 특정 column의 데이터 중 순위의 가장 첫 번째 값을 가져옴

<ex1>
-- 지역별로 가장 키가 큰 사람과의 키 차이를 조회
SELECT addr AS '주소',
	NAME AS '이름',
	height AS '키',
	height - FIRST_VALUE(height) OVER(PARTITION BY addr ORDER BY height DESC) AS '지역별로 가장 키가 큰 사람과의 키 차이'
FROM usertbl
ORDER BY addr;

<ex1>

 

'Database' 카테고리의 다른 글

[Database] DB 모델링  (0) 2024.05.22
[Database] 조인(JOIN)과 UNION 연산자 / 서브쿼리  (0) 2024.05.20
[Database] 데이터 형식(Data Type) & 함수 (1)  (0) 2024.05.17
[Database] SQL 기본 (2)  (0) 2024.05.17
[Database] SQL 기본 (1)  (0) 2024.05.16

계정관리


 

1. 계정 정보 확인

  • 계정에 대한 정보는  /etc/passwd 파일에 저장되어 있음
  •  /etc/passwd  파일의 구성 내용은 앞에서부터 사용자 ID, 암호, UID, GID, 설명, 홈 디렉터리, 로그인 쉘로 구성
  • 계정에 대한 패스워드는  /etc/shadow   파일에 저장되어 있음 (관리자 계정으로만 확인 가능)

 

2. 계정 생성

  • 계정을 생성하려면 adduser 명령어를 사용
sudo adduser [계정이름]
$ sudo adduser chaechae

계정 생성

 

3. 계정 삭제

  • 계정을 생성하려면 adduser 명령어를 사용
sudo userdel [사용자명]
$ sudo userdel chaechae

생성한 유저 삭제

# 유저를 생성하면서 만들어지는 폴더도 함께 삭제
sudo rm -r /home/chaechae

chaechae 폴더 삭제

 

4. 생성한 사용자로 로그인

$ su - test

test 사용자로 로그인

 

더보기

 

계정마다 권할을 설정하는 것은 번거러운 작업이기때문에 그룹을 설정하여 계정별로 권한을 설정


$ ls /home/beyond/
현재 test 계정이기 때문에 beyond에 접근할 수 없음
ls -l /home
기타 사용자에 test는 beyond에 접근 권한이 없을 확인
sudo ls /home/beyond
beyond 계정은 최초 계정이므로 sudo기능을 사용할 수 있지만 test는 불가능함

 

5. 계정 로그아웃

exit

test 사용자 로그아웃

 

 

 

파일 접근 권한


1. 접근 권한

  • 리눅스는 여러 사용자가 동시에 접속하여 사용하기 때문에 파일들에 대해 접근 권한을 부여 가능
  • 리눅스 파일에 대한 접근 권한의 종류에는 읽기(r), 쓰기(w), 실행(x) 권한이 존재
  • 접근 권한은 세 문자씩 묶어 한 세트로 구성되며 각 묶음 순서대로 소유자, 소유 그룹, 기타 사용자로 분류

 

2. 접근 권한 변경

  • 파일에 대한 접근 권한을 변경하려면 chmod 명령어를 사용
더보기
# hello.txt 파일과 temp 폴더를 생성

$ echo "Hello" > hello.txt
$ mkdir temp
hello.txt 파일과 temp 폴더를 생성

 

hello.txt 파일 정보
temp 폴더 정보
  • 권한 제거
# 사용자의 읽기 권한 삭제
chmod u-r helllo.txt

hello.txt에서 유저 읽기권한 삭제
사용자의 읽기 권한이 삭제

# 기타 사용자의 읽기 권한 삭제
chmod o-r hello.txt

hello.txt에서 기타사용자의 읽기권한 삭제
기타 사용자의 읽기 권한 삭제

# 디렉터리에 대해 읽기권한을 제거하면 ls 명령어 사용 불가
chmod u-r temp

유저로부터 temp 폴더의 읽기 권한을 제거

# 실행권한을 제거하면 해당 디렉터리로 이동하는 것이 불가(cd 명령어를 사용할 수 없음)
chmod u-x temp

유저로부터 temp 폴더의 실행 권한을 제거

# 파일의 쓰기 권한을 제거하면 해당 폴더에 새로운 파일이나 폴더를 생성하는 것이 불가
chmod u-w temp

유저로부터 temp 폴더의 쓰기 권한을 제거


  • 권한 추가
# 사용자에게 읽기권한 부여
chmod u+r hello.txt

읽기 권한 부여
유저에게 hello.txt에 대한 읽기 권한이 부여됨

#사용자에게 실행권한 부여
chmod u+x hello.txt

실행권한 부여
사용자에게 실행 권한이 부여됨


  • 모든 권한 변경
# 파일유형 |  rwx | rwx | rwx : rwx는 이진수로 표현
#662는 소유자 소유그룹 기타사용자에 대해 한자리씩 십진수로 권한 표현

chmod 662 temp

소유자 110 ❘ 소유그룹 010 ❘ 기타소유자 010

 

 

더보기

 

grep


grep alias .bashrc
alias가 포함된 모든 행을 출력

 

grep -c alias .bashrc
.bashrc에 존재하는 alias의 개수 출력

 

grep -i alias .bashrc
대소문자를 구별하지 않고 alias가 포함된 모든 행을 출력

 

grep -n alias .bashrc
alias가 포함된 모든 행을 행 번호와 함께 출력

 

# ls-l의 검색 결과의 문자 데이터에서 temp가 포함된 문자열을 출력
ls -l | grep temp
ls -l에서 temp를 찾는 방법



 

'Linux' 카테고리의 다른 글

[Linux] Vim / 텍스트 처리  (0) 2024.05.17
[Linux] 파일/디렉터리 조작  (0) 2024.05.17
[Linux] 파일/디렉터리  (0) 2024.05.17
[Linux] 리눅스(Linux)/ 셸(Shell)  (0) 2024.05.17
[Linux] ssh 인증키 설정  (0) 2024.05.14

Vim


1. Vim

  • 윈도에 메모장 맥의 텍스트 편집기와 같은 편집기로 대부분의 리눅스 배포판에 기본으로 설치되어 있는 편집기
더보기

<vim 설치>

#1
$ vim --version
vim --version을 통해 vim 설치 확인

#2
# sudo : 관리자 권한
$ sudo apt update
apt 패키지 update vim 설치 이전에 apt를 update하는 것을 추천

#3
$ sudo apt install vim
패스워드 입력후 y 입력하여 vim을 설치

#4
$ vim --version
vim --version을 통해 vim이 설치되었는지 확인

 

2. 실행과 종료

  • Vim을 실행하려면 vim 명령어를 사용
vim <파일명>
vim

vim 명령어를 입력시 화면

  • Vim을 실행할 때 파일 이름을 지정하면 해당 파일을 열 수 있음
  • 이때 존재하지 않는 파일을 지정하면 해당 이름으로 파일을 새로 생성
  • Vim을 종료하려면 Vim이 실행된 상태에서 :q를 입력하고 엔터

 

# 기존 파일 열기
$ echo "sample" > sample.txt

sample.txt 파일 생성

# vim 명령어로 텍스트편집기에 sample.txt파일 열기
 $ vim .sample.txt


# 새로운 파일 만들기 1

$ vim
$ :w[파일명]

hello1.txt 생성

 


# 새로운 파일 만들기 2
$ vim hello2.txt

# 파일 저장
$ :w

 

 

3. Vim의 모드

  • Vim은 다른 에디터와 달리 모드(Mode)라는 것이 존재
  • Vim은 명령어를 입력할 수 있는 보통 모드(Normal Mode)와 텍스트를 입력할 수 있는 입력 모드(Insert Mode)
  • Vim을 실행하면 보통 모드에서 시작
  •  i, a, o를 누르면 입력 모드가 되고 입력 모드, esc를 누르면 보통 모드
# vim 모드 사용
$ vim hello1.txt

보통모드

# 입력모드
i

# 내용을 입력하고 esc를 눌러 다시 보통모드로 전환

입력모드

# 저장 후 종료
:wq
# 파일 생성이 잘 되었는지 확인
$ cat hello1

cat 명령어로 변경 내용이 저장되었는지 확인

 

 

4. Vim 명령어

4.1. 파일 저장

  • 편집 중인 파일을 저장하려면 보통 모드에서 :w 명령어를 사용
    • 기존 파일을 열은 상태라면 덮어쓰게 되고, 새로운 파일 편집 중이라면 새로운 파일을 생성

 

4.2. 커서 이동

  • 단어 단위로 커서를 이동하려면 보통 모드에서 w, b 명령어를 사용
    • w는 다음 단어의 첫 글자로 이동
    • b는 이전 단어의 첫 글자로 이동
    • 공백을 기준으로 커서를 이동하고 싶을 때는 W, B 명령어를 사용한다.
  • 행의 처음과 끝으로 커서를 이동하려면 보통 모드에서 0, $ 명령어를 사용
  • 번호로 커서를 이동하려면 보통 모드에서 <행 번호>G 명령어를 사용
  • 파일의 처음으로 커서를 이동하려면 gg, 파일의 마지막으로 커서를 이동하려면 G 명령어를 사용
# set number 명령어
# 보통 모드에서
:set number

행별로 숫자 출력

 

4.3. 자르기(삭제), 복사, 붙여넣기

  • 문자 하나를 자르려면 보통 모드에서 x 명령어를 사용
  • 문자의 범위를 지정해서 자르려면 d 명령어로 범위를 지정해서 문자를 삭제 가능
    • d$는 현재 커서 위치에서 행의 마지막까지 잘라냄
    • d0는 현재 커서 위치에서 행의 시작까지 잘라냄
    • dl은 문자 한 개를 잘라냄
    • dw는 단어 한 개를 잘라냄
      - dW : 공백 전까지 단어 한개를 잘라냄
    • dgg는 현재 커서 위치의 행에서 문서 시작까지 잘라냄
    • dG는 현재 커서 위치의 행에서 문서 끝까지 잘라냄
  • 전체 행을 자르려면 보통 모드에서 dd 명령어를 사용한다.

 

4.4. 복사

  • 문자의 범위를 지정해서 복사하려면 y 명령어로 범위를 지정해서 문자를 복사
    • y$는 현재 커서 위치에서 행의 마지막까지 복사
    • y0는 현재 커서 위치에서 행의 시작까지 복사
    • yl은 문자 한 개를 복사
    • yw는 단어 한 개를 복사
    • ygg는 현재 커서 위치의 행에서 문서 시작까지 복사
    • yG는 현재 커서 위치의 행에서 문서 끝까지 복사.
  • 전체 행을 복사하려면 보통 모드에서 yy 명령어를 사용

 

4.5. 붙여넣기

  • 삭제(자르기), 복사한 텍스트는 보통 모드에서 p 명령어로 원하는 곳에 붙여 넣을 수 있음

 

4.6. 취소와 재실행

  • 보통 모드에서 u 명령어를 입력하면 방금 실행한 동작을 취소
  • 취소한 동작에 대해 다시 실행하고 싶은 경우에는 보통 모드에서 Ctrl + r 명령어를 입력

 

4.7. 검색

  • Vim은 파일에서 문자열을 검색할 수 있다.
    • /문자열은 문자열을 아래 방향으로 검색
    • ?문자열은 문자열을 위 방향으로 검색
    • n은 검색 결과가 여러 개라면 다음 검색 결과로 이동
    • N은 검색 결과가 여러 개라면 이전 검색 결과로 이동

 

 

텍스트 처리


1. 텍스트 처리

  • 리눅스에서는 애플리케이션의 데이터나 시스템의 설정 항목이 대부분 텍스트로 되어 있다.
  • 따라서 리눅스에는 텍스트를 효과적으로 다루는 명령어가 다수 존재한다.

 

2. 바이트 수, 단어 수, 행의 수 세기

  • 바이트 수, 단어 수, 행의 수를 출력하려면 wc 명령어를 사용
# 행의 수, 단어 수, 바이트 수를 출력
$ wc <파일 이름>

행 ❘ 단어 ❘ 바이트 ❘ 파일명
행의 수, 바이트 수 확인


# 행의 수만 출력
$ wc -l <파일 이름>

행의수 ❘ 파일명


# 단어 수만 출력
$ wc -w <파일 이름>

단어 수 ❘ 파일명


# 바이트 수만 출력
$ wc -c <파일 이름>

바이트 수 ❘ 파일명

 

3. 행 단위로 정렬

  • 행 단위로 정렬하여 출력하려면 sort 명령어를 사용

더보기
hello1.txt 내용
sample.txt 내용
# 공백 > 숫자 > 영어(글자수 적은 것 부터  |대문자 > 소문자 | 알파벳 순)
# > 한글(글자수 적은것부터 | 가나다순)

$ sort [파일명]

sort hello1.txt 결과
sort ssample.txt 결과


더보기
sample.txt 수정
sort sample.txt 결과
# 문자열을 code값으로 저장하기 때문에 숫자로 정렬하는 것이 아닌 code값으로 비교
# 숫자의 첫번째 자리의 code값으로 정렬한 후 다음번째 자리의 code값으로 정렬을 반복
# 숫자 값으로 정렬

$ sort -n <파일 이름>

sort -n sample.txt 정렬 결과

# 역순으로 정렬
$ sort -r <파일 이름>

sort -nr sample.txt 결과

# 숫자 값이 큰 순으로 정렬
$ sort -nr <파일 이름>

sort -nr sample.txt 결과

#명령어 여러개 한번에 사용하기 ( | : 파이프라인 기호)
# |는 앞에 있는 연산의 결과를 다음에 있는 다음 명령어에게 전달(표준 입력으로 전달)
# -k는 field를 나타내는 옵션
# 5는 5번째 filed를 의미

ls -l | sort -k 5

작업 디렉터리의 파일들을 바이트 순으로 정렬



4. 중복 제거

  • 연속된 중복 데이터를 하나만 출력하려면 uniq 명령어를 사용
더보기
sample.txt 내용
# 중복된 데이터를 제거
# 연속된 문자열에 한에서만 중복을 제거

$ uniq <파일 이름>

uniq sample.txt 결과

# sample.txt 정렬 후에 uniq 연산 실행

$ sort sample.txt | uniq

sample.txt 정렬 후에 uniq 연산 실행결과

# sort 옵션 -u와 sort sample.txt|uniq 결과 동일

$sort -u sample.txt

sort -u sample.txt 실행 결과

# 중복된 행의 개수 출력
$ uniq -c <파일 이름>

 

 

5. 일부 추출

  • 입력의 일부를 추출하여 출력하려면 cut 명령어를 사용
더보기
students.csv 파일 생성

 > .csv 파일 : 몇가지 필드를 콤마(,)로 구분한 텍스트 데이터 및 텍스트 파일

cut -d, -f 2 studnets.csv

두번째 필드의 데이터만 가져오기

#passwd 파일은 계정의 정보를 가지고 있음
cat /etc/passwd

 

cut -d : -f 1/ etc/passwd

cut -d : -f 1.7 /etc/passwd

 

cut -d : -f 1,7 etc/passwd | grep '/bin/bash'

 

 

6. 문자 치환

  • 문자를 치환하려면 tr 명령어를 사용
# tr은 표준 입력으로만 입력값을 받음

$ tr <치환 전 문자> <치환 후 문자>

 

#  passwd의 :(콜론) 기호를 ,(콤마)로 바꾸는 작업

#방법 1
cat /etc/passwd | tr : ,

#방법2
# 파일을 직접 지정한 것이 아님
tr : , < /etc/passwd

방법 1
방법 2

더보기

 

명령어에 따라 출력하는 값을 콘솔에 출력는데 이것을 표준출력이라고 함




 > 기호 : 표준 출력을 변경해줌 (표준 출력 리다이렉션)

# >>기호는 중복했을때 덮어쓸 것인지 진행여부 확인
ls > ls.txt​

 

ls의 결과를 ls.txt파일로 출력하도록 리다이렉션
에러출력을 리다이렉션할때는 2> 기호를 사용
ls /aaa 2> error.txt
표준 에러 출력을 리다이렉션

 

 <기호 : 표준입력을 변경해줌(표준 입력 리다이렉션)

# 표준출력인 키보드로부터가 아닌 students.csv파일을 입력으로 받도록 리다이렉션
cat students.csv​
표준 입력을 파일로 리다이렉션
# passwd의 소문자를 모두 대문자로 변경하는 작업
# | 명령어는 실행결과를 다음 명령어에게 표준 입력으로 전달해줌

cat /etc/passwd | tr a-z A-Z

 

7. 파일의 마지막 부분 출력

  • 파일의 마지막 내용부터 출력하려면 tail 명령어를 사용
# 파일의 마지막 10개 행을 출력
tail <파일 이름>

tail .bashrc 결과

# 파일의 마지막 5개 행을 출력
tail -n 5  <파일 이름>

tail -n 5 .bashrc 결과


  • tail 명령어에 -f 옵션을 사용하면 파일의 내용이 추가될 때마다 실시간으로 내용을 출력하여 파일을 모니터링할 수 있음
# 종료시 ctrl+c
tail -f <파일 이름>
$ tail -f sample.txt

tail -f sample.txt 실행결과 프롬프트가 변경되지 않음 파일에 내용이 추가된다면 추가할 수 있도록 계속 모니터링함

# tail -f sample.txt 실행중
# 다른 세션에서 sample.txt에 "오렌지" 텍스트 추가

ehco "오렌지" >> sample.txt

다른 세션에서 sample.txt에 내용을 추가

# 처음부터 계속 실행중
# 모니터링을 계속하다가 다른 세션에서 "오렌지" 데이터 추가시
# "오렌지" 출력

$ tail -f sample.txt

오렌지가 추가되면 tail -f sample.txt 명령어를 통해 모니터링하고 있기때문에 변경내용을 추가하여 출력해줌


  • tail의 반대로 동작하는 명령어는 head 명령어
# 파일의 처음 10개 행을 출력
head <파일 이름>
$ head .bashrc

head .bashrc 결과

# 파일의 처음 5개 행을 출력
head -n 5  <파일 이름>

head -n 5 .bashrc 결과

 

'Linux' 카테고리의 다른 글

[Linux] 계정 관리 / 파일 접근 권한  (0) 2024.05.18
[Linux] 파일/디렉터리 조작  (0) 2024.05.17
[Linux] 파일/디렉터리  (0) 2024.05.17
[Linux] 리눅스(Linux)/ 셸(Shell)  (0) 2024.05.17
[Linux] ssh 인증키 설정  (0) 2024.05.14

+ Recent posts