1. 데이터 정의어(DDL) 이란

테이블을 생성, 삭제하거나 컬럼을 추가, 수정, 삭제할 때 사용하는 명령어입니다.
크게 CREATE, ALTER, DROP, TRUNCATE로 구분됩니다.

 

2. 데이터 정의어 명령어 정리

1) CREATE

데이터베이스 또는 테이블을 생성할 때 사용합니다. 
create database 데이터베이스명;

show databases;

use 데이터베이스명;
create table 테이블명 (
       컬럼명 자료형 [제약조건 및 옵션],
       [키 제약조건 선언]
)
CREATE TABLE department (
	id INT(11) NOT NULL AUTO_INCREMENT,
	name VARCHAR(50) NULL DEFAULT NULL,
	PRIMARY KEY (id)
)

create table member(
  id int auto_increment not null,
  name varchar(50) not null,
  dept_id int null,
  primary key(id),
  constraint fk_department foreign key (dept_id) references department (id)
);
department 테이블과 member 테이블을 생성했습니다. member 테이블은 department의 id를 참조하고 있습니다.

 

2) 컬럼 옵션

auto_increment : 숫자 형에 사용가능 하며 자동으로 숫자가 증가하는 속성을 부여합니다. 
not null : null 값을 가질 수 없습니다.
unique : unique key 속성을 부여합니다. 해당 컬럼은 중복된 값을 가질 수 없습니다. 
default : 기본 값을 지정합니다.
check :  특정 값만 가질 수 있게 지정합니다.
primary key : 기본키로 지정합니다.
foreign key : 외래키로 지정합니다.
#컬럼 옵션 예제
create table member (
	id int auto_increment primary key,
	name varchar(50) not null,
	code char(1) not null default 'A',
	email varchar(100) unique,
	class char(1) check(class in (1,2,3,4)),
	dept_id int null,
	constraint fk_department foreign key (dept_id) references department (id)
)

3) ALTER

테이블을 수정할 때 사용하는 명령어 입니다.

3-1) 컬럼 추가

alter table 테이블명 add 컬럼명 컬럼타입 [옵션]

alter table member add column age int not null; 

3-2) 컬럼 수정

alter table 테이블명 modify 컬럼명 변경할데이터타입 [옵션]

alter table member modify name varchar(300) null

3-3) 컬럼 삭제

alter table 테이블명 drop 삭제할컬럼명

alter table member drop age;

3-4) 컬럼명 변경

alter table 테이블명 change 변경할컬럼명 새로운컬럼명 컬럼타입

alter table member change name title varchar(100);

3-5) 제약 조건 추가

alter table 테이블명 add constraint 제약조건명 제약조건(컬럼명..)

#유니크 제약조건 추가
alter table member add constraint uk_code_name unique key (code, name);

#기본키 제약조건 추가
alter table member add constraint pk_id_code primary key (id, code)

#외래키 제약조건 추가
#외래키를 지정할 경우 해당 컬럼에 index key가 함께 선언된다.
alter table member add constraint fk_dept_id foreign key (dept_id) references department (id)

3-6) 제약 조건 삭제

alter table 테이블명 drop constraint 제약조건명

#유니크 키 제거
alter table member drop constraint uk_code_name;

#외래키 제거
alter table member drop foreign key fk_dept_id

#인덱스 제거
alter table member drop constraint fk_dept_id

#제약조건명 조회방법
select * 
from information_schema.table_constraints
where TABLE_SCHEMA = '데이터베이스명' and TABLE_NAME = '테이블명'

3-7) 테이블 명 변경

alter table 테이블명 rename 새로운테이블명

alter table member rename customer;

 

4) DROP

데이터베이스 또는 테이블을 삭제할 때 사용합니다. 
drop database 데이터베이스명

drop database my_db;
drop table 테이블명

drop table member

 

5) TRUNCATE

테이블의 모든 내용을 지울 때 사용합니다.
truncate table 테이블명;

truncate table member;

 

'IT > Mysql & MariaDB' 카테고리의 다른 글

[Mysql] 조인 (JOIN) 이란?  (0) 2021.04.03
[Mysql] distinct와 group by의 차이  (0) 2021.03.28
[Mysql] group by와 having  (1) 2021.03.28
[Mysql] group by 시 가장 큰 값을 가진 row 조회하기  (0) 2021.03.27
[Mysql] delete join  (0) 2021.02.25

1. JOIN 이란?

한개 또는 여러개의 테이블을 결합하는 연산을 의미합니다. JOIN의 종류는 다음과 같습니다.

cross join
inner join
left outer join
right outer join
full outer join
self join

 

join을 설명하기 이전에 테스트로 사용될 테이블 부터 생성해 보겠습니다.

CREATE TABLE `department` (
	`id` INT(11) NOT NULL AUTO_INCREMENT,
	`name` VARCHAR(50) NULL DEFAULT NULL,
	PRIMARY KEY (`id`)
)

CREATE TABLE `employee` (
	`id` INT(11) NOT NULL AUTO_INCREMENT,
	`name` VARCHAR(100) NULL DEFAULT NULL,
	`salary` INT(11) NULL DEFAULT NULL,
	`dept_id` INT(11) NULL DEFAULT NULL,
	`manager_id` INT(11) NULL DEFAULT NULL,
	PRIMARY KEY (`id`),
	CONSTRAINT `fk_department_id` FOREIGN KEY (`dept_id`) REFERENCES `department` (`id`),
	CONSTRAINT `fk_manager_id` FOREIGN KEY (`manager_id`) REFERENCES `employee` (`id`)
)

INSERT INTO `department` (`id`, `name`) VALUES (1, '사업부');
INSERT INTO `department` (`id`, `name`) VALUES (2, '개발부');
INSERT INTO `department` (`id`, `name`) VALUES (3, '영업부');

INSERT INTO `employee` (`id`, `name`, `salary`, `dept_id`, `manager_id`) VALUES (1, 'kim', 3000, 2, NULL);
INSERT INTO `employee` (`id`, `name`, `salary`, `dept_id`, `manager_id`) VALUES (2, 'park', 2600, 2, NULL);
INSERT INTO `employee` (`id`, `name`, `salary`, `dept_id`, `manager_id`) VALUES (3, 'lee', 7000, 1, NULL);
INSERT INTO `employee` (`id`, `name`, `salary`, `dept_id`, `manager_id`) VALUES (4, 'go', 3400, 2, NULL);
INSERT INTO `employee` (`id`, `name`, `salary`, `dept_id`, `manager_id`) VALUES (5, 'jang', 4000, 1, NULL);
INSERT INTO `employee` (`id`, `name`, `salary`, `dept_id`, `manager_id`) VALUES (6, 'hong', 5500, 1, NULL);
INSERT INTO `employee` (`id`, `name`, `salary`, `dept_id`, `manager_id`) VALUES (7, 'sin', 1800, 2, 2);
INSERT INTO `employee` (`id`, `name`, `salary`, `dept_id`, `manager_id`) VALUES (8, 'lim', 3400, 2, NULL);
INSERT INTO `employee` (`id`, `name`, `salary`, `dept_id`, `manager_id`) VALUES (9, 'chang', 4400, 3, NULL);
INSERT INTO `employee` (`id`, `name`, `salary`, `dept_id`, `manager_id`) VALUES (10, 'ho', 1800, NULL, 1);
INSERT INTO `employee` (`id`, `name`, `salary`, `dept_id`, `manager_id`) VALUES (11, 'coco', 8900, NULL, NULL);

employee 테이블
department 테이블

 

1) cross join 

조인한 테이블을 교차 결합할 때 사용합니다. 결과 수는 조인한 테이블의 행을 곱한 수입니다.
select * from employee cross join department;
# 33개가 조회된다.

 

2) inner join

inner join은 특정 조건에 맞는 행만 결합할 때 사용합니다.
select a.*, b.name
from employee a
inner join department b on (b.id = a.dept_id)
on 절 다음에 조인 조건을 명시하며 조건에 맞는 행을 결합하여 출력합니다.
위 조건은 employee 테이블의 dept_id와 department 테이블의 id가 같은 경우 결합하도록 명시했습니다.

여기서 employee 테이블의 ho와 coco는 dept_id가 null이기 때문에 조인되지 않습니다.

 

3) left outer join

left outer join은 왼쪽 테이블을 대상으로 오른쪽 테이블과 결합하는 연산이며, 여기서 포인트는 조인 조건이 맞지 않더라도 왼쪽에 있는 테이블의 모든 행이 출력된다는 점입니다. 조건이 맞을 경우 그 만큼 행이 추가되서 조회됩니다.
select a.*, b.name
from employee a
left outer join department b on (b.id = a.dept_id)

employee 테이블을 대상으로 left outer join을 했기 때문에, employee 테이블의 모든 행이 출력되었고, 그 중 조건이 맞는 경우 department의 name이 출력되게 했습니다. 조건이 맞지 않을 경우 null이 출력됩니다.

 

좀 더 다양한 테스트를 하기 위해 access_log 테이블을 추가해 보겠습니다.

# employee의 접근 기록을 저장하는 테이블
CREATE TABLE `access_log` (
	`id` INT(11) NOT NULL AUTO_INCREMENT,
	`access_dt` DATETIME NULL DEFAULT '',
	`emp_id` INT(11) NULL DEFAULT NULL,
	PRIMARY KEY (`id`),
	CONSTRAINT `fk_access_log_emp_id` FOREIGN KEY (`emp_id`) REFERENCES `employee` (`id`)
)

INSERT INTO `access_log` (`id`, `access_dt`, `emp_id`) VALUES (1, '2021-03-28 16:30:55', 1);
INSERT INTO `access_log` (`id`, `access_dt`, `emp_id`) VALUES (2, '2021-03-28 16:30:58', 1);
INSERT INTO `access_log` (`id`, `access_dt`, `emp_id`) VALUES (3, '2021-03-28 16:31:01', 1);
INSERT INTO `access_log` (`id`, `access_dt`, `emp_id`) VALUES (4, '2021-03-28 16:31:04', 2);
INSERT INTO `access_log` (`id`, `access_dt`, `emp_id`) VALUES (5, '2021-03-28 16:31:05', 3);
INSERT INTO `access_log` (`id`, `access_dt`, `emp_id`) VALUES (6, '2021-03-28 16:31:06', 3);
INSERT INTO `access_log` (`id`, `access_dt`, `emp_id`) VALUES (7, '2021-03-28 16:31:08', 3);
INSERT INTO `access_log` (`id`, `access_dt`, `emp_id`) VALUES (8, '2021-03-28 17:31:11', 4);
INSERT INTO `access_log` (`id`, `access_dt`, `emp_id`) VALUES (9, '2021-03-28 18:31:13', 1);

access_log 테이블

 

access_log 테이블은 employee의 접근 기록을 저장하는 테이블입니다. 위 정보를 봐서 유추해볼 수 있는 점은 emp_id가 1인 사원은 4번의 출입 기록이 있고, 2는 1번, 3은 3번, 4는 1번의 출입 기록이 있는 것을 알 수 있습니다.
더 정확한 정보를 알기 위해서 employee 테이블과 access_log를 left outer join 해보겠습니다.
select a.*, b.access_dt
from employee a
left outer join access_log b on (b.emp_id = a.id)

employee 테이블을 대상으로 access_log 테이블과 left outer join을 했기 때문에 employee 테이블의 모든 행이 출력되었고, 접근 기록이 있는 만큼 추가로 조회됩니다.

right outer join은 left outer join 시 테이블의 위치만 바뀐 것이며, full outer join 설명은 생략하겠습니다.

 

4) self join

self join은 계층 구조를 표현 할 때 사용하며 한 개의 테이블로 표현이 가능합니다.  
select emp.*, manager.name AS 'manager_name'
from employee emp
join employee manager on (manager.id = emp.manager_id)
employee 테이블을 조인 하였으며, employee의 id와 manager_id 가 같은 경우 조회됩니다.

1. 예제 테이블 및 데이터

CREATE TABLE `employee` (
	`id` INT(11) NOT NULL AUTO_INCREMENT,
	`name` VARCHAR(100) NULL DEFAULT NULL,
	`salary` INT(11) NULL DEFAULT NULL
	PRIMARY KEY (`id`)
)

CREATE TABLE `access_log` (
	`id` INT(11) NOT NULL AUTO_INCREMENT,
	`access_dt` DATETIME NULL DEFAULT '',
	`emp_id` INT(11) NULL DEFAULT NULL,
	PRIMARY KEY (`id`),
	CONSTRAINT `fk_access_log_emp_id` FOREIGN KEY (`emp_id`) REFERENCES `employee` (`id`)
)


INSERT INTO `employee` (`id`, `name`, `salary`) VALUES (1, 'kim', 3000);
INSERT INTO `employee` (`id`, `name`, `salary`) VALUES (2, 'park', 2600);
INSERT INTO `employee` (`id`, `name`, `salary`) VALUES (3, 'lee', 7000);
INSERT INTO `employee` (`id`, `name`, `salary`) VALUES (4, 'go', 3400);

INSERT INTO `access_log` (`id`, `access_dt`, `emp_id`) VALUES (1, '2021-03-28 16:30:55', 1);
INSERT INTO `access_log` (`id`, `access_dt`, `emp_id`) VALUES (2, '2021-03-28 16:30:58', 1);
INSERT INTO `access_log` (`id`, `access_dt`, `emp_id`) VALUES (3, '2021-03-28 16:31:01', 1);
INSERT INTO `access_log` (`id`, `access_dt`, `emp_id`) VALUES (4, '2021-03-28 16:31:04', 2);
INSERT INTO `access_log` (`id`, `access_dt`, `emp_id`) VALUES (5, '2021-03-28 16:31:05', 3);
INSERT INTO `access_log` (`id`, `access_dt`, `emp_id`) VALUES (6, '2021-03-28 16:31:06', 3);
INSERT INTO `access_log` (`id`, `access_dt`, `emp_id`) VALUES (7, '2021-03-28 16:31:08', 4);
INSERT INTO `access_log` (`id`, `access_dt`, `emp_id`) VALUES (8, '2021-03-28 17:31:11', 4);
INSERT INTO `access_log` (`id`, `access_dt`, `emp_id`) VALUES (9, '2021-03-28 18:31:13', 1);

# 사원 접근 정보 조회
select emp.name, access.access_dt
from employee emp
join access_log access on (access.emp_id = emp.id)

2. distinct 란

distinct는 unique한 행을 조회 할 경우 사용합니다.  내부 동작 방식은 group by와 동일 하지만 중복 제거 후 정렬을 하지 않는다는 차이점이 있습니다. 그리고 distinct 명령어는 반드시 select 첫번째 컬럼 앞에 입력해야합니다.

1) 예제

2021-03-28 16:00:00 ~ 2021-03-28 16:59:59 에 접근한 사원 명을 중복없이 조회하고 싶다면 다음과 같은 쿼리를 입력하면 됩니다.
select distinct emp.id, emp.name
from employee emp
join access_log access on (access.emp_id = emp.id)
where access.access_dt between '2021-03-28 16:00:00' and '2021-03-28 16:59:59' 

#결과
# 1 kim
# 2 park
# 3 lee
여기서 select 절을 "select distinct emp.id, emp.name, access.access.dt"로 변경할 경우 어떤 결과 값이 출력될까요?
이경우 emp.id, emp.name, access.access.dt를 하나의 unique한 행으로 묶기 때문에 다음과 같이 출력됩니다.

 

3. group by 란

group by는 특정 컬럼을 기준으로 그룹화 하는 명령어입니다. 
그룹화를 하면 집계함수를 이용해서 통계데이터(평균, 합계 등)을 구할 수 있습니다. 
그룹화 작업을 진행하면서 내부적으로 정렬을 수행합니다. 정렬을 수행하고 싶지 않다면 order by null 을 추가해주면 됩니다.

자세한 내용을 알고 싶다면 아래 링크로 이동해주세요.
2021.03.28 - [IT/Mysql & MariaDB] - [Mysql] group by와 having

 

4. distinct와 group by의 차이점

distinct와 group by 모두 중복된 데이터를 지울 수 있지만 용도 별로 사용되는 경우가 다릅니다.
distinct는 unique한 행을 조회할 때 사용하고, group by는 집계 데이터를 구할 때 사용합니다.

그래서 distinct와 group by 별로 추출 가능한 데이터가 다릅니다.

특정 시간 사이에 접근한 사원수를 구할 경우 distinct가 유리하고,
사원 별로 특정 시간에 접근한 회수를 구할 경우 group by가 유리합니다. 

정확한 이해를 위해서 아래 두 쿼리를 한가지 방식으로만 조회하는 쿼리를 작성해 보시기 바랍니다. 
# '2021-03-28 16:00:00' ~ '2021-03-28 16:59:59' 사이에 접근한 사원 수 
select count(distinct emp.id)
from employee emp
join access_log access on (access.emp_id = emp.id)
where access.access_dt between '2021-03-28 16:00:00' and '2021-03-28 16:59:59' 
# 결과
# 3


# 사원 별로 '2021-03-28 16:00:00' ~ '2021-03-28 16:59:59' 사이에 접근한 회수 
select emp.name, count(emp.id)
from employee emp
join access_log access on (access.emp_id = emp.id)
where access.access_dt between '2021-03-28 16:00:00' and '2021-03-28 16:59:59' 
group by emp.id

# 결과
# kim 3
# park 1
# lee 3

'IT > Mysql & MariaDB' 카테고리의 다른 글

[Mysql] 데이터 정의어 (DDL)  (1) 2021.04.04
[Mysql] 조인 (JOIN) 이란?  (0) 2021.04.03
[Mysql] group by와 having  (1) 2021.03.28
[Mysql] group by 시 가장 큰 값을 가진 row 조회하기  (0) 2021.03.27
[Mysql] delete join  (0) 2021.02.25

1. group by란?

group by는 특정 컬럼을 기준으로 그룹화 하는 명령어입니다. 
그룹화를 하면 집계함수를 이용해서 통계데이터(평균, 합계 등)을 구할 수 있습니다.
select 컬럼
from 테이블명
where 조건
group by 그룹컬럼
[having 조건]

 

2. group by 예제

#예제 테이블 및 데이터
CREATE TABLE `department` (
	`id` INT(11) NOT NULL AUTO_INCREMENT,
	`name` VARCHAR(50) NULL DEFAULT NULL,
	PRIMARY KEY (`id`)
)

CREATE TABLE `employee` (
	`id` INT(11) NOT NULL AUTO_INCREMENT,
	`name` VARCHAR(100) NULL DEFAULT NULL,
	`salary` INT(11) NULL DEFAULT NULL,
	`dept_id` INT(11) NULL DEFAULT NULL,
	PRIMARY KEY (`id`),
	CONSTRAINT `fk_department_id` FOREIGN KEY (`dept_id`) REFERENCES `department` (`id`)
)

INSERT INTO `department` (`id`, `name`) VALUES (1, '사업부');
INSERT INTO `department` (`id`, `name`) VALUES (2, '개발부');
INSERT INTO `department` (`id`, `name`) VALUES (3, '영업부');

INSERT INTO `employee` (`id`, `name`, `salary`, `dept_id`) VALUES (6, 'hong', 5500, 1);
INSERT INTO `employee` (`id`, `name`, `salary`, `dept_id`) VALUES (3, 'lee', 7000, 1);
INSERT INTO `employee` (`id`, `name`, `salary`, `dept_id`) VALUES (5, 'jang', 4000, 1);
INSERT INTO `employee` (`id`, `name`, `salary`, `dept_id`) VALUES (8, 'lim', 3400, 2);
INSERT INTO `employee` (`id`, `name`, `salary`, `dept_id`) VALUES (7, 'sin', 2800, 2);
INSERT INTO `employee` (`id`, `name`, `salary`, `dept_id`) VALUES (1, 'kim', 3000, 2);
INSERT INTO `employee` (`id`, `name`, `salary`, `dept_id`) VALUES (4, 'go', 3400, 2);
INSERT INTO `employee` (`id`, `name`, `salary`, `dept_id`) VALUES (2, 'park', 2600, 2);
INSERT INTO `employee` (`id`, `name`, `salary`, `dept_id`) VALUES (9, 'chang', 4400, 3);
INSERT INTO `employee` (`id`, `name`, `salary`, `dept_id`) VALUES (10, 'ho', 3600, 3);

# 데이터 조회
select 
  emp.id,
  emp.name,
  emp.salary,
  dept.name as 'dept_name'
from employee emp
join department dept on (dept.id = emp.dept_id)
order by emp.dept_id

사업부, 개발부, 영업부가 있고 각 부서에 소속된 사원들이 있을 때, 부서 별로 소속된 사원의 연봉 정보(합계, 평균, 최소, 최대)를 얻고 싶다면 다음과 같은 쿼리를 입력하면 됩니다. 

1) 부서 별 연봉 정보 추출 쿼리

select 
  dept.name,
  count(emp.id) as '소속인원',
  sum(emp.salary) as '총 연봉',
  avg(emp.salary) as '평균 연봉',
  min(emp.salary) as '최저 연봉',
  max(emp.salary) as '최고 연봉'
from employee emp
join department dept on (dept.id = emp.dept_id)
group by dept.id
;
employee 테이블과 department 테이블을 조인하고 부서 dept.id 컬럼으로 그룹화를 했습니다. 
그러면 내부적으로 employee.dept_id 컬럼의 같은 값 끼리 그룹핑이 됩니다. 부서별로 그룹핑된 데이터를 이용해서 소속 인원, 총 연봉, 평균 연봉, 최저 연봉, 최고 연봉을 추출할 수 있습니다.

 

2) having

having 명령어를 이용하면 집계된 데이터로 조건을 부여할 수 있습니다. 
집계 함수의 결과를 조건으로 이용하려면 반드시 having 절에서 사용해야 하며 where에서 사용하면 에러가 발생합니다.
#평균 연봉이 5000만원 이상인 부서 정보를 조회해라
select 
  dept.name,
  count(emp.id) as '소속인원',
  sum(emp.salary) as '총 연봉',
  avg(emp.salary) as '평균 연봉',
  min(emp.salary) as '최저 연봉',
  max(emp.salary) as '최고 연봉'
from employee emp
join department dept on (dept.id = emp.dept_id)
group by dept.id
having avg(emp.salary) >= 5000

 

3) 그룹화 하지 않은 컬럼을 조회 할 경우

select 
  dept.name,
  emp.name,
  max(emp.salary) as '최고 연봉'
from employee emp
join department dept on (dept.id = emp.dept_id)
group by dept.id

개발부에서 가장 높은 연봉을 받는 사원은 lim이다

부서 별로 가장 높은 연봉을 받는 사원 정보를 조회하고 싶을 때 위와 같이 조회하는 실수를 범할 수 있습니다.
실제로 위와 같이 조회하면 emp.name에 엉뚱한 이름이 조회가 됩니다.

그룹화 하지 않은 컬럼을 조회할 경우 집계 함수로 감싸야합니다. 여기서 그룹화한 테이블은 department 테이블이고, department의 id로 그룹화 했기 때문에 department 별로 정보를 추출 할 수 있지만 employee 테이블은 그룹화하지 않았기 때문에 employee name을 조회하면 엉뚱한 데이터가 조회됩니다.

부서별로 가장 높은 연봉을 받는 사원을 조회하고 싶다면 아래 링크를 참조해주세요.
2021.03.27 - [IT/Mysql & MariaDB] - [Mysql] group by 시 가장 큰 값을 가진 row 조회하기

 

4) order by

SELECT 쿼리 실행 시 실행 순서는 다음과 같습니다. 
1. FROM
2. WHERE
3. GROUP BY
4. HAVING
5. ORDER BY
6. SELECT
7. LIMIT

group by는 order by가 수행되기 전에 실행됩니다. 
집계된 데이터로 정렬을 하고 싶다면 다음과 같이 쿼리를 입력하면 됩니다.
# 부서 별로 최고 연봉을 조회하고 최고 연봉 내림차순으로 정렬하라
select 
  dept.name,
  max(emp.salary) as '최고 연봉'
from employee emp
join department dept on (dept.id = emp.dept_id)
group by dept.id
order by avg(emp.salary) desc

 

DB 쿼리문을 작성 할 때, 특정 컬럼의 최대 값, 최소 값을 구해야할 경우가 있습니다.
최대 값, 최소 값을 구하기는 쉽지만, 최대, 최소 값을 가진 Row를 조회해야하는 경우 원하는 결과가 안나올 수 있습니다.
이때 사용할 수 있는 몇가지 방법을 알려드리겠습니다.
(더 좋은 방법이 있다면 댓글로 남겨주세요!)

테이블 생성 및 데이터 삽입 쿼리입니다.

CREATE TABLE `employee` (
	`id` INT(11) NOT NULL AUTO_INCREMENT,
	`name` VARCHAR(100) NULL DEFAULT NULL,
	`salary` INT(11) NULL DEFAULT NULL,
	`dept_id` INT(11) NULL DEFAULT NULL,
	PRIMARY KEY (`id`),
	INDEX `fk_department_id` (`dept_id`),
	CONSTRAINT `fk_department_id` FOREIGN KEY (`dept_id`) REFERENCES `department` (`id`)
)

CREATE TABLE `department` (
	`id` INT(11) NOT NULL AUTO_INCREMENT,
	`name` VARCHAR(50) NULL DEFAULT NULL,
	PRIMARY KEY (`id`)
)

INSERT INTO `department` (`id`, `name`) VALUES (1, '사업부');
INSERT INTO `department` (`id`, `name`) VALUES (2, '개발부');
INSERT INTO `department` (`id`, `name`) VALUES (3, '영업부');

INSERT INTO `employee` (`id`, `name`, `salary`, `dept_id`) VALUES (6, 'hong', 5500, 1);
INSERT INTO `employee` (`id`, `name`, `salary`, `dept_id`) VALUES (3, 'lee', 7000, 1);
INSERT INTO `employee` (`id`, `name`, `salary`, `dept_id`) VALUES (5, 'jang', 4000, 1);
INSERT INTO `employee` (`id`, `name`, `salary`, `dept_id`) VALUES (8, 'lim', 3400, 2);
INSERT INTO `employee` (`id`, `name`, `salary`, `dept_id`) VALUES (7, 'sin', 2800, 2);
INSERT INTO `employee` (`id`, `name`, `salary`, `dept_id`) VALUES (1, 'kim', 3000, 2);
INSERT INTO `employee` (`id`, `name`, `salary`, `dept_id`) VALUES (4, 'go', 3400, 2);
INSERT INTO `employee` (`id`, `name`, `salary`, `dept_id`) VALUES (2, 'park', 2600, 2);
INSERT INTO `employee` (`id`, `name`, `salary`, `dept_id`) VALUES (9, 'chang', 4400, 3);
INSERT INTO `employee` (`id`, `name`, `salary`, `dept_id`) VALUES (10, 'ho', 3600, 3);

 

1. employee 테이블에서 최고 연봉을 받는 Row 조회하기

1) order by 사용하기

select 
  b.name,
  a.name, 
  a.salary
from employee a
join department b on (b.id = a.dept_id)
ORDER BY a.salary desc
limit 1;

#결과
#사업부 lee 7000
연봉을 내림차순하고 한개만 조회하도록하여 연봉이 가장 높은 row를 조회하는 방법입니다. 
최고 연봉을 가진 사람이 여러명이어도 한명만 조회됩니다. (정렬 조건에 따라서 출력되는 row가 달라집니다.)

 

2) where 절에 서브쿼리 사용하기

select 
  b.name,
  a.name, 
  a.salary
from employee a
join department b on (b.id = a.dept_id)
WHERE a.salary = (SELECT MAX(a.salary) from employee a)

#결과
#사업부 lee 7000
where절에 서브쿼리를 이용하는 방법입니다. 서브쿼리 구문을 통해 최고 연봉 값을 구하고 해당 값과 같은 연봉을 가진 row를 조회합니다. 최고 연봉가진 사람이 두명이라면 두개의 행이 출력됩니다. 

 

2. 부서 별로 가장 높은 연봉을 받는 Row 조회하기

select 
  b.name,
  a.name, 
  a.salary
from employee a
join department b on (b.id = a.dept_id)
join (
	select max(salary) as 'max_salary'
	from employee
	group by dept_id
) c on (a.salary = c.max_salary);

#결과
#사업부 lee 7000
#개발부 go 3400
#개발부 lim 3400
#영업부 chang 4400
from 절에 서브쿼리를 사용해서 부서별로 가장높은 연봉을 가진 inline view를 생성하고 최고 연봉을 기준으로 조인하는 방법입니다.

 

'IT > Mysql & MariaDB' 카테고리의 다른 글

[Mysql] distinct와 group by의 차이  (0) 2021.03.28
[Mysql] group by와 having  (1) 2021.03.28
[Mysql] delete join  (0) 2021.02.25
[Mysql] Date_Format 날짜 포멧  (0) 2021.01.27
[MariaDB] Sequence 사용 방법  (0) 2021.01.15
DELETE [alias, ...]
FROM table_a AS a
LEFT JOIN table_b AS b ON (b.id = a.b_id)
WHERE [조건문]
[alias, ...]  부분에 삭제할 테이블의 alias를 입력하면 된다. (ex: DELETE a, b ... 또는 DELETE b ...)
table_a와 table_b가 참조 관계이고, 두 테이블의 행을 동시에 삭제할 경우 참조무결성 에러가 발생할 수 있다. 

1. 날짜 포멧 기본 문법

DATE_FORMAT(date, format)

 

1) 예제

SELECT DATE_FORMAT(NOW(),'%Y-%m-%d %H:%i:%s') #2021-01-27 16:30:45

 

2. 포멧 옵션

Format	Description
%a : Abbreviated weekday name (Sun to Sat)
%b : Abbreviated month name (Jan to Dec)
%c : Numeric month name (0 to 12)
%D : Day of the month as a numeric value, followed by suffix (1st, 2nd, 3rd, ...)
%d : Day of the month as a numeric value (01 to 31)
%e : Day of the month as a numeric value (0 to 31)
%f : Microseconds (000000 to 999999)
%H : Hour (00 to 23)
%h : Hour (00 to 12)
%I : Hour (00 to 12)
%i : Minutes (00 to 59)
%j : Day of the year (001 to 366)
%k : Hour (0 to 23)
%l : Hour (1 to 12)
%M : Month name in full (January to December)
%m : Month name as a numeric value (00 to 12)
%p : AM or PM
%r : Time in 12 hour AM or PM format (hh:mm:ss AM/PM)
%S : Seconds (00 to 59)
%s : Seconds (00 to 59)
%T : Time in 24 hour format (hh:mm:ss)
%U : Week where Sunday is the first day of the week (00 to 53)
%u : Week where Monday is the first day of the week (00 to 53)
%V : Week where Sunday is the first day of the week (01 to 53). Used with %X
%v : Week where Monday is the first day of the week (01 to 53). Used with %x
%W : Weekday name in full (Sunday to Saturday)
%w : Day of the week where Sunday=0 and Saturday=6
%X : Year for the week where Sunday is the first day of the week. Used with %V
%x : Year for the week where Monday is the first day of the week. Used with %v
%Y : Year as a numeric, 4-digit value
%y : Year as a numeric, 2-digit value

출처 : https://www.w3schools.com/sql/func_mysql_date_format.asp

 

1. Sequence

ID 값을 숫자가 아닌 다양한 방식으로 저장하고 싶은 경우 사용합니다. Thread-safety 하게 ID를 발급 받을 수 있으며, AUTO_INCREMENT 대신 사용할 수 있습니다.
Sequence는 값을 캐시하므로 경우에 따라 AUTO_INCREMENT 보다 빠를 수 있다고 합니다.

MariaDB의 Sequence 기능은 10.3버전 부터 지원됩니다.

 

2. Sequence 문법

CREATE [OR REPLACE] [TEMPORARY] SEQUENCE [IF NOT EXISTS] sequence_name
[ INCREMENT [ BY | = ] increment ]
[ MINVALUE [=] minvalue | NO MINVALUE | NOMINVALUE ]
[ MAXVALUE [=] maxvalue | NO MAXVALUE | NOMAXVALUE ]
[ START [ WITH | = ] start ] [ CACHE [=] cache | NOCACHE ]
[ CYCLE | NOCYCLE]
[table_options]

 

3. 간단한 Sequence 사용 방법

# 10.3 버전 이상인지 확인 
SELECT VERSION();

 

1) Sequence 생성

#시작값이 1이고 1씩 증가하는 "my_seq" Sequence를 생성
CREATE SEQUENCE my_seq START WITH 1 INCREMENT BY 1;

2) NEXTVAL

# 다음 sequence를 반환한다. 
# 처음 생성 한 것이면 start 값을 반환 
# thread-safety
SELECT NEXTVAL(my_seq);

3) LASTVAL

# 현재 sequence를 반환
# NEXTVAL을 한번도 실행시키지 않았다면 NULL 반환
SELECT LASTVAL(my_seq);

4) Sequence 초기화

# my_seq Sequence를 1로 초기화 한다.
# nextval를 실행하지 않은 상태로 lastval를 실행하면 초기화 전 값이 반환된다.
# 즉 한번이라도 nextval을 실행해야지 sequence가 초기화된다. 
ALTER SEQUENCE my_seq RESTART 1;

 


참조 

https://mariadb.com/kb/en/create-sequence/

+ Recent posts