포스코DX X 비트교육센터 6기 - SQL


모델링 TOOL

  • starUML
  • EA
  • erWin
  • workbench

image

image

image

자동으로 UML 만들어줌.

SELECT 연습

select * from employees;

select * from salaries where emp_no='10002';


--
-- SELECT 연습 
--

-- 예1: DEPERTMENTS 테이블의 모든 데이터를 출력 ( LIMIT : 1000) 
SELECT * FROM departments;

-- 프로젝션 (성능에도 영향이 있음; projection)
-- 예2: employyes 테이블에서 직원 이름, 성별, 입사일을 출력
SELECT first_name as '이름', gender  as '성' , hire_date as '입사일' FROM employees;

-- distinct 
-- 예3: titles 테이블에서 모든 직급을 출력하라.
-- limit는 상단에 limit to 10rows를 통해 자동으로 붙어서 생략이 가능하다. 대신 붙이면, 시작과 끝 index 설정 가능.
SELECT distinct title from titles limit 0, 10;

-- 예4: titles 테이블에서 모든 직급은 어떤 것들이 있는지 직급이름을 한 번씩만 출력하세요.
select distinct title from titles;

--
-- where 절
--

-- 예제1: 비교연산자: emplyees 테이블에서 1991년 이전에 입사한 직원의 이름, 
--                성별, 입사일을 출력 
select first_name, gender, hire_date
  from employees
  where hire_date < '1991-01-01'
  order by hire_date desc;
  
-- 예제2: 논리연산자: employees 테이블에서 1989년 입사한 여직원의 이름, 성별, 입사일을 출력하세요
  select first_name, gender, hire_date
  from employees
  where hire_date < '1991-01-01' and gender ='f'
  order by hire_date desc;
  
  -- 예제3: in 연산자: dept_emp 테이블에서 부서 번호가 d005이거나 d009에 속한 사원의 사번, 부서 번호를 출력
    select emp_no, dept_no
  from dept_emp
  where dept_no = 'd005' and dept_no ='d009';
  
  -- or
  select emp_no, dept_no
  from dept_emp
  where dept_no in ('d005' , 'd009');
  
  -- 예제4: like 검색: employees 테이블에서 1989년에 입사한 직원들의 이름, 입사일을 출력
  select first_name, hire_date
  from employees
  where hire_date >= '1989-01-01'
  and hire_date <= '1989-12-31';
  
  -- or
  select first_name, hire_date
  from employees
  where hire_date like '1989%';
  
  -- or
  select first_name, hire_date
  from employees
  where hire_date between '1989-01-01'
  and '1989-12-31';
  
  
  --
  -- order by
  --
  -- 예1: employyes 테이블에서 직원 이름, 성별, 입사일을 빠른 순으로 출력
  select concat(first_name, ' ', last_name) as 'full name', gender, hire_date
  from employees
  order by hire_date asc;
  
  -- 예2: salaries 테이블에서 2001년 월급이 가장 높은 순으로 사번월급을 출력
  select emp_no, salary, from_date, to_date
  from salaries
  where to_date like '2001%'
  or from_date like '2001%'
  order by salary desc;
  
  -- 직급은?
  select * from titles where emp_no = 43624;
  
  -- 예3: 남자 직원의 이름, 성별, 입사일을 선임순으로 출력
  select first_name, gender, hire_date
  from employees
  where gender ='m'
  order by hire_date asc;
  
  -- 예4: 직원들의 사번, 월급을 사번 순으로 출력
  select emp_no, salary
  from salaries
  order by emp_no;

문자열함수 연습

--
-- 문자열 함수
--


-- upper
select upper('seoul'), ucase('SeOuL') from dual;
select upper(first_name) from employees;

-- lower
select lower('SEOUL'), lcase('SeOuL') from dual;
select lower(first_name) from employees;

-- substring(문자열, index, length) >> index가 1부터 시작함. 
select substring('Hello World', 3, 2) from dual;

 -- 예1: like 검색: employees 테이블에서 1989년에 입사한 직원들의 이름, 입사일을 출력
  select first_name, hire_date
  from employees
  where substring(hire_date, 1, 4) = '1989';
  
  -- lpad, rpad: 정렬함수
  select lpad('1234', 10, '-') from dual; -- 결과 : ------1234
  select lpad('1234', 10, ' ') from dual; -- 결과 :       1234
  
  select rpad('1234', 10, '-') from dual; -- 결과 : 1234------
  select lpad('1234', 10, ' ') from dual; -- 결과 : 1234
  
  -- 예) 직원들의 월급을 오르쪽 정렬
  select lpad(salary, 10, ' ')
  from salaries;
  
  -- trim, ltrim, rtrim
  select 
    concat('---', ltrim('   hello   '), '---'), -- 결과: ---hello   ---
    concat('---', rtrim('   hello   '), '---'), -- 결과: ---   hello---
    concat('---', trim(leading ' ' from '   hello   '), '---'), -- 결과: ---hello   ---
    concat('---', trim(trailing ' ' from '   hello   '), '---'), -- 결과: ---   hello---
    concat('---', trim(both ' ' from '   hello   '), '---') -- 결과: ---hello---
  from dual;

-- length
select length('Hello World') from dual;


DB 처리와 java 백엔드와 js 프론트엔드와의 역할

데이터 처리는 sql에서 처리하고 java에선 데이터를 화면에 뿌리는 작업만 하기. 문자열 처리가 sql이 더 좋다. java는 명확한 비즈니스 로직이 보여야 한다.

표현은 js에게 맡기고@

수학 함수

--
-- 수학 함수
--


-- abs 절대값
select abs(1), abs(-1) from dual;

-- floor
select floor(3.14), floor(3.9999) from dual; -- 결과 : 3, 3

-- ceil
select ceil(3.14), ceil(3.9999) from dual; -- 결과 : 4, 4

-- mod
select mod(10, 3) from dual; -- 결과: 1

-- round(x) : x에 가장 가까운 정수
-- round(x, d) : x값 중에 d 자리에 가장 근접한 실수
select round(1.498), round(1.498,1)  from dual; -- 결과: 1, 1.5

-- power(x, y) : x의 y승
select power(2,10), pow(2,10) from dual; -- 결과: 1024, 1024

-- sign(x): 양수 1, 음수 -1, 0 1
select sign(20), sign(-100), sign(0) from dual; -- 결과: 1, -1, 0

-- greatest(x, y, ...) 최대값, least(x,y, ...) 최소값
select greatest(10,40,20,50,30), least(10,  40,30, 50, 40) from dual; -- 결과: 50, 1
select greatest('A', 'C', 'X', 'O', 'N' ), least('hello', 'hela', 'hell') from dual; -- 결과: X, hela

날짜 함수

--
-- 날짜 함수
--

-- 날짜만 : curdate(), current_date 
select curdate(), current_date() from dual;

-- 날짜와 시간 : now () vs sysdate()
-- now : 게시판 작성 시간 >> 자바로 하지 말고, DB에서 해야한다. 쿼리 시작 시간
-- sysdate : 호출 시간  
select now(), sysdate() from dual;
select now(), sleep(2), now() from dual; -- sleep 해도 같은 시간이 찍힘
select now(), sleep(2), sysdate() from dual; -- sleep 이후에 2초가 늘어 있다.

-- date_format
-- 2023년 8월 30일 11시 37분 57초
select date_format(now(), '%Y년 %m월 %d일 %h시 %i분 %s초') from dual;

-- period_diff >>  P1과 P2사이 달의 숫자를 반환하는 함수
-- formatting: yymm, YYYYmm
-- 예) 근무 개월(2023년 기준)
select first_name, 
hire_date, 
abs(period_diff(date_format(hire_date, '%y%m'), date_format(curdate(), '%y%m')) ) as month
from employees;

-- date_add(adddate), date_sub(=subdate)
-- 날짜를 date 타입의 컬럼이나 값에 type(year, month, day)의 표현식으로 더하거나
-- 예) 각 사원의 근속 년 수가 5년이 되는 날에 휴가를 보내준다면 각 사원들의 근속 휴가 날짜는?

select first_name, hire_date, date_add(hire_date, interval 5 year)
from employees;

집계 함수

-- 1) 집계쿼리: select절에 통계함수(avg, max, min, count, sum, stddev, ...)

select avg(salary), sum(salary) from salaries;

-- 2) select 절에 그룹함수(=통계함수, 집계함수)있는 경우, 어떤 컬럼도 select 절에 올 수 없다. (집계함수의 결과는 하나의 row이기에)
-- emp_no는 아무런 의미가 없다.
-- 오류!!!
select emp_no, avg(salary) from salaries;

-- 3) 쿼리 순서
--   1. from : 테이블에 접근
--   2. where : 조건에 맞는 row를 선택
--   3. projection : 집계(임시 테이블, 메모리 캐시)
--   4. 결과를 반환: 출력

-- 예) 사번이 10060인 사원이 받은 평균 연봉은?
select avg(salary) from salaries
where emp_no='10060';

-- 4) group by에 참여 컬럼은 projection이 가능하다: select 절에 올 수 있다.
-- 예) 사원별 평균 연봉 
select emp_no, avg(salary) from salaries
group by emp_no
order by avg(salary) desc;

-- 5) Having 
-- 집계 결과(결과 테이블)에서 row를 선택해야하는 경우
-- 이미 where 절은 실행이 되었기 때문에 having 절에서 조건을 주어야 한다.
-- 예) 평균 연봉이 60000 달러 이상인 사원의 사번과 평균 연봉을 출력
select emp_no, avg(salary) from salaries
group by emp_no
having avg(salary) >= 60000
order by avg(salary) asc;

-- 6) order by
-- order by는 항상 맨 마지막 출력 전에 한다.
select emp_no, avg(salary) from salaries
group by emp_no
having avg(salary) >= 60000
order by avg(salary) asc;

-- 주의) 
-- 예) 사번이 10060인 사원의 사번, 평균 급여, 급여 총합을 출력 _ 이번엔 집계함수와 emp_no를 넣어도 논리적으로 맞지만, 문법적으로는 틀림. 
-- 문법 오류로 오라클의 경우 바로 에러가 발생.
-- 의미적으로만 맞다. where절의 조건 때문이다.
select avg(salary), sum(salary), emp_no 
from salaries 
where emp_no=10060;

-- 문법적으로 옳다.
select avg(salary), sum(salary)
from salaries
group by emp_no
having emp_no=10060;

JOIN

image

  • Inner Join
    • equi join : 값이 정확하게 일치하는 경우에 = 연산자를 사용해서 JOIN
    • Ansi join

image

image

-- 
-- inner join
--

-- 예1) 현재 근무하고 있는 직원 사번과, 이름, 직책을 모두 출력
select a.emp_no, a.first_name, b.title
from employees a, titles b
where a.emp_no = b.emp_no -- join 조건 (n-1)
and b.to_date = '9999-01-01'; -- row 선택 조건
 

  • Outer Join :