# 데이터베이스 a4가 존재하면 삭제
DROP DATABASE IF EXISTS a4;

# 데이터베이스 a4 생성
CREATE DATABASE a4;

# 데이터베이스 a4 선택
USE a4;

# 회원 테이블 생성, loginId, loginPw, `name`
## 조건 : loginId 칼럼에 UNIQUE INDEX 없이
CREATE TABLE `member` (
    id INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
    PRIMARY KEY(id),
    regDate DATETIME NOT NULL,
    loginId CHAR(50) NOT NULL,
    loginPw VARCHAR(100) NOT NULL,
    `name` CHAR(100) NOT NULL
);

# 회원 2명 생성
## 조건 : (loginId = 'user1', loginPw = 'user1', `name` = '홍길동')
## 조건 : (loginId = 'user2', loginPw = 'user2', `name` = '홍길순')
INSERT INTO `member`
SET regDate = NOW(),
loginId = 'user1',
loginPw = 'user1',
`name` = '홍길동';

INSERT INTO `member`
SET regDate = NOW(),
loginId = 'user2',
loginPw = 'user2',
`name` = '홍길순';

# 회원 2배 증가 쿼리만들고 회원이 백만명 넘을 때 까지 반복 실행
## 힌트1 : INSERT INTO `tableName` (col1, col2, col3, col4)
## 힌트2 : SELECT NOW(), UUID(), 'pw', '아무개'

INSERT INTO `member` (regDate, loginId, loginPw, `name`)
SELECT NOW(), UUID(), 'pw', '아무개'
FROM `member`;

# 회원수 확인
SELECT COUNT(*)
FROM `member`;

# 검색속도 확인
## 힌트 : SQL_NO_CACHE
SELECT SQL_NO_CACHE *
FROM `member`
WHERE loginId = 'user1';

# 유니크 인덱스를 loginID 칼럼에 걸기
## 설명 : mysql이 loginId의 고속검색을 위한 부가데이터를 자동으로 관리(생성/수정/삭제) 한다.
## 설명 : 이게 있고 없고가, 특정 상황에서 어마어마한 성능차이를 가져온다.
## 설명 : 생성된 인덱스의 이름은 기본적으로 칼럼명과 같다.
ALTER TABLE `member` ADD UNIQUE INDEX (`loginId`); 

# 검색속도 확인, loginId 가 'user1' 인 회원 검색
SELECT SQL_NO_CACHE *
FROM `member`
WHERE loginId = 'user1';

# 인덱스 삭제, `loginId` 이라는 이름의 인덱스 삭제
ALTER TABLE `member` DROP INDEX `loginId`;

# 회원 테이블 삭제
DROP TABLE `member`;

# 회원 테이블을 생성하는데, loginId에 uniqueIndex 까지 걸어주세요.
CREATE TABLE `member` (
    id INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
    PRIMARY KEY(id),
    regDate DATETIME NOT NULL,
    loginId CHAR(50) UNIQUE NOT NULL,
    loginPw VARCHAR(100) NOT NULL,
    `name` CHAR(100) NOT NULL
);

# 회원 2명 생성
## 조건 : (loginId = 'user1', loginPw = 'user1', `name` = '홍길동')
## 조건 : (loginId = 'user2', loginPw = 'user2', `name` = '홍길순')
INSERT INTO `member`
SET regDate = NOW(),
loginId = 'user1',
loginPw = 'user1',
`name` = '홍길동';

INSERT INTO `member`
SET regDate = NOW(),
loginId = 'user2',
loginPw = 'user2',
`name` = '홍길순';

# 회원수 확인
SELECT COUNT(*) FROM `member`;

# 인덱스 쓰는지 확인
## 힌트 : EXPLAIN SELECT SQL_NO_CACHE * ~
EXPLAIN SELECT SQL_NO_CACHE *
FROM `member`
WHERE loginId = 'user1';

# 게시물 테이블 생성(title, body, writerName, memberId)
CREATE TABLE `article` (
    id INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
    PRIMARY KEY(id),
    regDate DATETIME NOT NULL,
    title CHAR(200) NOT NULL,
    `body` TEXT NOT NULL,
    `writerName` CHAR(100) NOT NULL,
    memberId INT(10) UNSIGNED NOT NULL
);

# 1번 회원이 글 1 작성(title = '글 1 제목', `body` = '글 1 내용')
INSERT INTO article
SET regDate = NOW(),
title = '글 1 제목',
`body` = '글 1 내용',
writerName = '홍길동',
memberId = 1;

# 2번 회원이 글 2 작성(title = '글 2 제목', `body` = '글 2 내용')
INSERT INTO article
SET regDate = NOW(),
title = '글 2 제목',
`body` = '글 2 내용',
writerName = '홍길순',
memberId = 2;

# 1번 회원이 글 3 작성(title = '글 3 제목', `body` = '글 3 내용')
INSERT INTO article
SET regDate = NOW(),
title = '글 3 제목',
`body` = '글 3 내용',
writerName = '홍길동',
memberId = 1;

# 전체글 조회
SELECT *
FROM article;

# 1번회원의 이름변경 홍길동 => 홍길동2
UPDATE `member`
SET `name` = '홍길동2'
WHERE id = 1;

# 전체글 조회, 여전히 게시물 테이블에는 이전 이름이 남아 있음
SELECT *
FROM article;

# 게시물 테이블에서 writerName 삭제
ALTER TABLE article DROP COLUMN writerName;

# INNER JOIN 을 통해서 두 테이블을 조회한 결과를 합침, ON 없이
SELECT * FROM article
INNER JOIN `member`;

# INNER JOIN 을 통해서 두 테이블을 조회한 결과를 합침, 올바른 조인 조건

## 힌트 : 이걸로 조인조건을 걸 칼럼 조사
## SELECT article.id, article.memberId, member.id AS "회원테이블_번호"
## FROM article
## INNER JOIN `member`;

# 조인 완성, ON 까지 추가
SELECT A.*, M.name AS writerName
FROM article AS A
INNER JOIN `member` AS M
ON A.memberId = M.id;
# a6 DB 삭제/생성/선택
DROP DATABASE IF EXISTS a6;
CREATE DATABASE a6;
USE a6;

# 부서(홍보, 기획)
# 주의 : INT(10)이 10바이트라는 강사의 설명은 잘못 되었습니다. 그냥 INT라고 쓰시면 됩니다.
CREATE TABLE dept (
    id INT UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
    regDate DATETIME NOT NULL,
    `name` CHAR(100) NOT NULL UNIQUE
);

INSERT INTO dept
SET regDate = NOW(),
`name` = '홍보';

INSERT INTO dept
SET regDate = NOW(),
`name` = '기획';

# 사원(홍길동/홍보/5000만원, 홍길순/홍보/6000만원, 임꺽정/기획/4000만원)
# 주의 : INT(10)이 10바이트라는 강사의 설명은 잘못 되었습니다. 그냥 INT라고 쓰시면 됩니다.
CREATE TABLE emp (
    id INT UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
    regDate DATETIME NOT NULL,
    `name` CHAR(100) NOT NULL,
    deptId INT UNSIGNED NOT NULL,
    salary INT UNSIGNED NOT NULL
);

INSERT INTO emp
SET regDate = NOW(),
`name` = '홍길동',
deptId = 1,
salary = 5000;

INSERT INTO emp
SET regDate = NOW(),
`name` = '홍길순',
deptId = 1,
salary = 6000;

INSERT INTO emp
SET regDate = NOW(),
`name` = '임꺽정',
deptId = 2,
salary = 4000;

# 사원 수 출력
SELECT COUNT(*)
FROM emp;

# 가장 큰 사원 번호 출력
SELECT MAX(id)
FROM emp;

# 가장 고액 연봉
SELECT MAX(salary)
FROM emp;

# 가장 저액 연봉
SELECT MIN(salary)
FROM emp;

# 회사에서 1년 고정 지출(인건비)
SELECT SUM(salary)
FROM emp;

# 부서별, 1년 고정 지출(인건비)
SELECT deptId, SUM(salary)
FROM emp
GROUP BY deptId;

# 부서별, 최고연봉
SELECT deptId, MAX(salary)
FROM emp
GROUP BY deptId;

# 부서별, 최저연봉
SELECT deptId, MIN(salary)
FROM emp
GROUP BY deptId;

# 부서별, 평균연봉
SELECT deptId, AVG(salary)
FROM emp
GROUP BY deptId;

# 부서별, 부서명, 사원리스트, 평균연봉, 최고연봉, 최소연봉, 사원수
## V1(조인 안한 버전)
SELECT E.deptId AS 부서번호,
GROUP_CONCAT(E.name) AS 사원리스트,
TRUNCATE(AVG(E.salary), 0) AS 평균연봉,
MAX(E.salary) AS 최고연봉,
MIN(E.salary) AS 최소연봉,
COUNT(*) AS 사원수
FROM emp AS E
GROUP BY E.deptId;

## V2(조인해서 부서명까지 나오는 버전)
SELECT D.name AS 부서,
GROUP_CONCAT(E.name) AS 사원리스트,
TRUNCATE(AVG(E.salary), 0) AS 평균연봉,
MAX(E.salary) AS 최고연봉,
MIN(E.salary) AS 최소연봉,
COUNT(*) AS 사원수
FROM emp AS E
INNER JOIN dept AS D
ON E.deptId = D.id
GROUP BY E.deptId;

## V3(V2에서 평균연봉이 5000이상인 부서로 추리기)
SELECT D.name AS 부서,
GROUP_CONCAT(E.name) AS 사원리스트,
TRUNCATE(AVG(E.salary), 0) AS 평균연봉,
MAX(E.salary) AS 최고연봉,
MIN(E.salary) AS 최소연봉,
COUNT(*) AS 사원수
FROM emp AS E
INNER JOIN dept AS D
ON E.deptId = D.id
GROUP BY E.deptId
HAVING `평균연봉` >= 5000;

## V4(V3에서 HAVING 없이 서브쿼리로 수행)
### HINT, UNION을 이용한 서브쿼리
# SELECT *
# FROM (
#     SELECT 1 AS id
#     UNION
#     SELECT 2
#     UNION
#     SELECT 3
# ) AS A

SELECT *
FROM (
    SELECT D.name AS `부서명`,
    GROUP_CONCAT(E.`name`) AS `사원리스트`,
    TRUNCATE(AVG(E.salary), 0) AS `평균연봉`,
    MAX(E.salary) AS `최고연봉`,
    MIN(E.salary) AS `최소연봉`,
    COUNT(*) AS `사원수`
    FROM emp AS E
    INNER JOIN dept AS D
    ON E.deptId = D.id
    WHERE 1
    GROUP BY E.deptId
) AS D
WHERE D.`평균연봉` >= 5000;
# a5 데이터베이스 삭제/생성/선택
drop database if exists a5;

create database a5;

use a5;

# 부서(dept) 테이블 생성 및 홍보부서 기획부서 추가
create table dept (
    id INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
    PRIMARY KEY(id),
    regDate DATETIME NOT NULL,
    `name` CHAR(100) NOT NULL UNIQUE
);

insert into dept
SET regDate = NOW(),
`name` = '홍보';

INSERT INTO dept
SET regDate = NOW(),
`name` = '기획';

select *
from dept;

# 사원(emp) 테이블 생성 및 홍길동사원(홍보부서), 홍길순사원(홍보부서), 임꺽정사원(기획부서) 추가
create table emp (
    id int(10) unsigned not null auto_increment,
    primary key(id),
    regDate datetime not null,
    `name` char(100) not null,
    deptName char(100) not null
);

insert into emp
set regDate = NOW(),
`name` = '홍길동',
deptName = '홍보';

INSERT INTO emp
SET regDate = NOW(),
`name` = '홍길순',
deptName = '홍보';

INSERT INTO emp
SET regDate = NOW(),
`name` = '임꺽정',
deptName = '기획';

# 홍보를 마케팅으로 변경
select *
from dept;

update dept
set `name` = '마케팅'
where `name` = '홍보';

select *
from emp;

update emp
set deptName = '마케팅'
where deptName = '홍보';

SELECT *
FROM emp;

# 마케팅을 홍보로 변경

UPDATE dept
SET `name` = '홍보'
WHERE `name` = '마케팅';

SELECT *
FROM dept;

UPDATE emp
SET deptName = '홍보'
WHERE deptName = '마케팅';

SELECT *
FROM emp;

# 홍보를 마케팅으로 변경
# 구조를 변경하기로 결정(사원 테이블에서, 이제는 부서를 이름이 아닌 번호로 기억)
ALTER TABLE emp add COLUMN deptId int(10) unsigned not null;

select *
from emp;

update emp
set deptId = 1
where deptName = '홍보';

UPDATE emp
SET deptId = 2
WHERE deptName = '기획';

SELECT *
FROM emp;

alter table emp drop column deptName;

select *
from dept;

UPDATE dept
SET `name` = '마케팅'
WHERE `name` = '홍보';

select *
from dept;

select *
from emp;

# 사장님께 드릴 인명록을 생성
select *
from emp;

# 사장님께서 부서번호가 아니라 부서명을 알고 싶어하신다.
# 그래서 dept 테이블 조회법을 알려드리고 혼이 났다.
SELECT *
FROM dept
where id = 1;

# 사장님께 드릴 인명록을 생성(v2, 부서명 포함, ON 없이)
# 이상한 데이터가 생성되어서 혼남
SELECT emp.*, dept.name AS `부서명`
FROM emp
inner join dept;

# 사장님께 드릴 인명록을 생성(v3, 부서명 포함, 올바른 조인 룰(ON) 적용)
# 보고용으로 좀 더 편하게 보여지도록 고쳐야 한다고 지적받음
SELECT emp.*, dept.id, dept.name AS `부서명`
FROM emp
inner join dept
ON emp.deptId = dept.id;

# 사장님께 드릴 인명록을 생성(v4, 사장님께서 보시기에 편한 칼럼명(AS))
SELECT emp.id AS `사원번호`,
emp.name AS `사원명`,
DATE(emp.regDate) AS `입사일`,
dept.name AS `부서명`
FROM emp
INNER JOIN dept
ON emp.deptId = dept.id
order by `부서명`, `사원번호`;

★App 클래스를 만들어 Main class의 부담을 줄임

package com.KoreaIT.java.AM;

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

import com.KoreaIT.java.AM.dto.Article;
import com.KoreaIT.java.AM.dto.Member;
import com.KoreaIT.java.AM.util.Util;

public class App {

	List<Article> articles;
	List<Member> members;

	public App() {
		articles = new ArrayList<>();
		members = new ArrayList<>();
	}

	public void start() {
		System.out.println("==프로그램 시작==");

		makeTestData();

		Scanner sc = new Scanner(System.in);

		int lastArticleId = 3;
		int lastMemberId = 0;

		while (true) {
			System.out.print("명령어 > ");
			String command = sc.nextLine().trim();

			if (command.length() == 0) {
				System.out.println("명령어를 입력해주세요");
				continue;
			}

			if (command.equals("exit")) {
				break;
			}

			if (command.equals("member join")) {
				int id = lastMemberId + 1;
				String regDate = Util.getNowDateTimeStr();
				String loginId = null;
				while (true) {
					System.out.print("로그인 아이디 : ");
					loginId = sc.nextLine();

					if (isJoinableLoginId(loginId) == false) {
						System.out.println("이미 사용중인 아이디입니다");
						continue;
					}
					break;
				}

				String loginPw = null;
				String loginPwConfirm = null;

				while (true) {
					System.out.print("로그인 비밀번호 : ");
					loginPw = sc.nextLine();
					System.out.print("로그인 비밀번호 확인: ");
					loginPwConfirm = sc.nextLine();

					if (loginPw.equals(loginPwConfirm) == false) {
						System.out.println("비밀번호를 확인해주세요");
						continue;
					}
					break;
				}

				System.out.print("이름 : ");
				String name = sc.nextLine();

				Member member = new Member(id, regDate, regDate, loginId, loginPw, name);
				members.add(member);

				System.out.printf("%d번 회원이 가입되었습니다\n", id);
				lastMemberId++;

			} else if (command.equals("article write")) {
				int id = lastArticleId + 1;
				System.out.print("제목 : ");
				String regDate = Util.getNowDateTimeStr();
				String title = sc.nextLine();
				System.out.print("내용 : ");
				String body = sc.nextLine();

				Article article = new Article(id, regDate, regDate, title, body);
				articles.add(article);

				System.out.printf("%d번글이 생성되었습니다\n", id);
				lastArticleId++;

			} else if (command.startsWith("article list")) {
				if (articles.size() == 0) {
					System.out.println("게시글이 없습니다");
					continue;
				}

				String searchKeyword = command.substring("article list".length()).trim();

				List<Article> forPrintArticles = articles;

				if (searchKeyword.length() > 0) {
					System.out.println("searchKeyword : " + searchKeyword);
					forPrintArticles = new ArrayList<>();

					for (Article article : articles) {
						if (article.title.contains(searchKeyword)) {
							forPrintArticles.add(article);
						}
					}
					if (forPrintArticles.size() == 0) {
						System.out.println("검색 결과가 없습니다");
						continue;
					}
				}

				System.out.println(" 번호  //  제목    //  조회  ");
				for (int i = forPrintArticles.size() - 1; i >= 0; i--) {
					Article article = forPrintArticles.get(i);
					System.out.printf("  %d   //   %s   //   %d  \n", article.id, article.title, article.hit);
				}

			} else if (command.startsWith("article detail")) {

				String[] cmdDiv = command.split(" ");

				if (cmdDiv.length < 3) {
					System.out.println("명령어를 확인해주세요");
					continue;
				}

				int id = Integer.parseInt(cmdDiv[2]);

				Article foundArticle = getArticleById(id);

				if (foundArticle == null) {
					System.out.printf("%d번 게시물은 존재하지 않습니다\n", id);
					continue;
				}

				foundArticle.hit++;

				System.out.println("번호 : " + foundArticle.id);
				System.out.println("작성날짜 : " + foundArticle.regDate);
				System.out.println("수정날짜 : " + foundArticle.updateDate);
				System.out.println("제목 : " + foundArticle.title);
				System.out.println("내용 : " + foundArticle.body);
				System.out.println("조회 : " + foundArticle.hit);

			} else if (command.startsWith("article modify")) {

				String[] cmdDiv = command.split(" ");

				if (cmdDiv.length < 3) {
					System.out.println("명령어를 확인해주세요");
					continue;
				}

				int id = Integer.parseInt(cmdDiv[2]);

				Article foundArticle = getArticleById(id);

				if (foundArticle == null) {
					System.out.printf("%d번 게시물은 존재하지 않습니다\n", id);
					continue;
				}
				System.out.print("새 제목 : ");
				String updateDate = Util.getNowDateTimeStr();
				String newTitle = sc.nextLine();
				System.out.print("새 내용 : ");
				String newBody = sc.nextLine();

				foundArticle.title = newTitle;
				foundArticle.body = newBody;
				foundArticle.updateDate = updateDate;

				System.out.println(id + "번 글을 수정했습니다");

			} else if (command.startsWith("article delete")) {

				String[] cmdDiv = command.split(" ");

				if (cmdDiv.length < 3) {
					System.out.println("명령어를 확인해주세요");
					continue;
				}

				int id = Integer.parseInt(cmdDiv[2]);

				int foundIndex = getArticleIndexById(id);

				if (foundIndex == -1) {
					System.out.printf("%d번 게시물은 존재하지 않습니다\n", id);
					continue;
				}

				articles.remove(foundIndex);
				System.out.println(id + "번 글을 삭제했습니다");

			} else {
				System.out.println("존재하지 않는 명령어입니다");
			}
		}

		System.out.println("==프로그램 끝==");

		sc.close();

	}

	private boolean isJoinableLoginId(String loginId) {
		int index = getMemberIndexByLoginId(loginId);

		if (index == -1) {
			return true;
		}

		return false;
	}

	private int getMemberIndexByLoginId(String loginId) {
		int i = 0;
		for (Member member : members) {
			if (member.loginId.equals(loginId)) {
				return i;
			}
			i++;
		}
		return -1;
	}

	private int getArticleIndexById(int id) {
		int i = 0;
		for (Article article : articles) {
			if (article.id == id) {
				return i;
			}
			i++;
		}
		return -1;
	}

	private Article getArticleById(int id) {
		int index = getArticleIndexById(id);

		if (index != -1) {
			return articles.get(index);
		}

		return null;
	}

	private void makeTestData() {
		System.out.println("테스트를 위한 데이터를 생성합니다");
		articles.add(new Article(1, Util.getNowDateTimeStr(), Util.getNowDateTimeStr(), "제목1", "제목1", 11));
		articles.add(new Article(2, Util.getNowDateTimeStr(), Util.getNowDateTimeStr(), "제목2", "제목2", 22));
		articles.add(new Article(3, Util.getNowDateTimeStr(), Util.getNowDateTimeStr(), "제목3", "제목3", 33));
	}

}

굉장히 간략해진 Main 클래스

package com.KoreaIT.java.AM;

public class Main {
	public static void main(String[] args) {
		new App().start();
	}
}

dto 패키지를 만들어

 

Dto,Article,Member 클래스를 나눔

package com.KoreaIT.java.AM.dto;

public class Article extends Dto {
	public String title;
	public String body;
	public int hit;

	public Article(int id, String regDate, String updateDate, String title, String body) {
		this(id, regDate, updateDate, title, body, 0);
	}

	public Article(int id, String regDate, String updateDate, String title, String body, int hit) {
		this.id = id;
		this.regDate = regDate;
		this.updateDate = updateDate;
		this.title = title;
		this.body = body;
		this.hit = hit;
	}
}

//////////////////////


package com.KoreaIT.java.AM.dto;

public class Dto {
	public int id;
	public String regDate;
	public String updateDate;
}


///////////
package com.KoreaIT.java.AM.dto;

public class Member extends Dto {
	public String loginId;
	public String loginPw;
	public String name;

	public Member(int id, String regDate, String updateDate, String loginId, String loginPw, String name) {
		this.id = id;
		this.regDate = regDate;
		this.updateDate = updateDate;
		this.loginId = loginId;
		this.loginPw = loginPw;
		this.name = name;
	}
}

//////

Util 클래스의 util 패키지

package com.KoreaIT.java.AM.util;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

public class Util {
	/** 포맷팅 현재 날짜/시간 반환 Str */
	public static String getNowDateTimeStr() {
		// 현재 날짜/시간
		LocalDateTime now = LocalDateTime.now();
		// 포맷팅
		String formatedNow = now.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
		// 포맷팅 현재 날짜/시간 출력

		return formatedNow;
	}
}
package com.KoreaIT.java.AM;

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

public class Main {
	static List<Article> articles = new ArrayList<>();
	static List<Member> members = new ArrayList<>();

	public static void main(String[] args) {
		System.out.println("==프로그램 시작==");

		makeTestData();

		Scanner sc = new Scanner(System.in);

		int lastArticleId = 3;
		int lastMemberId = 0;

		while (true) {
			System.out.print("명령어 > ");
			String command = sc.nextLine().trim();

			if (command.length() == 0) {
				System.out.println("명령어를 입력해주세요");
				continue;
			}

			if (command.equals("exit")) {
				break;
			}

			if (command.equals("member join")) {
				int id = lastMemberId + 1;
				String regDate = Util.getNowDateTimeStr();
				String loginId = null;
				while (true) {
					System.out.print("로그인 아이디 : ");
					loginId = sc.nextLine();

					if (isJoinableLoginId(loginId) == false) {
						System.out.println("이미 사용중인 아이디입니다");
						continue;
					}
					break;
				}

				String loginPw = null;
				String loginPwConfirm = null;

				while (true) {
					System.out.print("로그인 비밀번호 : ");
					loginPw = sc.nextLine();
					System.out.print("로그인 비밀번호 확인: ");
					loginPwConfirm = sc.nextLine();

					if (loginPw.equals(loginPwConfirm) == false) {
						System.out.println("비밀번호를 확인해주세요");
						continue;
					}
					break;
				}

				System.out.print("이름 : ");
				String name = sc.nextLine();

				Member member = new Member(id, regDate, regDate, loginId, loginPw, name);
				members.add(member);

				System.out.printf("%d번 회원이 가입되었습니다\n", id);
				lastMemberId++;

			} else if (command.equals("article write")) {
				int id = lastArticleId + 1;
				System.out.print("제목 : ");
				String regDate = Util.getNowDateTimeStr();
				String title = sc.nextLine();
				System.out.print("내용 : ");
				String body = sc.nextLine();

				Article article = new Article(id, regDate, regDate, title, body);
				articles.add(article);

				System.out.printf("%d번글이 생성되었습니다\n", id);
				lastArticleId++;

			} else if (command.startsWith("article list")) {
				if (articles.size() == 0) {
					System.out.println("게시글이 없습니다");
					continue;
				}

				String searchKeyword = command.substring("article list".length()).trim();

				List<Article> forPrintArticles = articles;

				if (searchKeyword.length() > 0) {
					System.out.println("searchKeyword : " + searchKeyword);
					forPrintArticles = new ArrayList<>();

					for (Article article : articles) {
						if (article.title.contains(searchKeyword)) {
							forPrintArticles.add(article);
						}
					}
					if (forPrintArticles.size() == 0) {
						System.out.println("검색 결과가 없습니다");
						continue;
					}
				}

				System.out.println(" 번호  //  제목    //  조회  ");
				for (int i = forPrintArticles.size() - 1; i >= 0; i--) {
					Article article = forPrintArticles.get(i);
					System.out.printf("  %d   //   %s   //   %d  \n", article.id, article.title, article.hit);
				}

			} else if (command.startsWith("article detail")) {

				String[] cmdDiv = command.split(" ");

				if (cmdDiv.length < 3) {
					System.out.println("명령어를 확인해주세요");
					continue;
				}

				int id = Integer.parseInt(cmdDiv[2]);

				Article foundArticle = getArticleById(id);

				if (foundArticle == null) {
					System.out.printf("%d번 게시물은 존재하지 않습니다\n", id);
					continue;
				}

				foundArticle.hit++;

				System.out.println("번호 : " + foundArticle.id);
				System.out.println("작성날짜 : " + foundArticle.regDate);
				System.out.println("수정날짜 : " + foundArticle.updateDate);
				System.out.println("제목 : " + foundArticle.title);
				System.out.println("내용 : " + foundArticle.body);
				System.out.println("조회 : " + foundArticle.hit);

			} else if (command.startsWith("article modify")) {

				String[] cmdDiv = command.split(" ");

				if (cmdDiv.length < 3) {
					System.out.println("명령어를 확인해주세요");
					continue;
				}

				int id = Integer.parseInt(cmdDiv[2]);

				Article foundArticle = getArticleById(id);

				if (foundArticle == null) {
					System.out.printf("%d번 게시물은 존재하지 않습니다\n", id);
					continue;
				}
				System.out.print("새 제목 : ");
				String updateDate = Util.getNowDateTimeStr();
				String newTitle = sc.nextLine();
				System.out.print("새 내용 : ");
				String newBody = sc.nextLine();

				foundArticle.title = newTitle;
				foundArticle.body = newBody;
				foundArticle.updateDate = updateDate;

				System.out.println(id + "번 글을 수정했습니다");

			} else if (command.startsWith("article delete")) {

				String[] cmdDiv = command.split(" ");

				if (cmdDiv.length < 3) {
					System.out.println("명령어를 확인해주세요");
					continue;
				}

				int id = Integer.parseInt(cmdDiv[2]);

				int foundIndex = getArticleIndexById(id);

				if (foundIndex == -1) {
					System.out.printf("%d번 게시물은 존재하지 않습니다\n", id);
					continue;
				}

				articles.remove(foundIndex);
				System.out.println(id + "번 글을 삭제했습니다");

			} else {
				System.out.println("존재하지 않는 명령어입니다");
			}
		}

		System.out.println("==프로그램 끝==");

		sc.close();
	}

	private static boolean isJoinableLoginId(String loginId) {
		int index = getMemberIndexByLoginId(loginId);

		if (index == -1) {
			return true;
		}

		return false;
	}

	private static int getMemberIndexByLoginId(String loginId) {
		int i = 0;
		for (Member member : members) {
			if (member.loginId.equals(loginId)) {
				return i;
			}
			i++;
		}
		return -1;
	}

	private static int getArticleIndexById(int id) {
		int i = 0;
		for (Article article : articles) {
			if (article.id == id) {
				return i;
			}
			i++;
		}
		return -1;
	}

	private static Article getArticleById(int id) {
		int index = getArticleIndexById(id);

		if (index != -1) {
			return articles.get(index);
		}

		return null;
	}

	private static void makeTestData() {
		System.out.println("테스트를 위한 데이터를 생성합니다");
		articles.add(new Article(1, Util.getNowDateTimeStr(), Util.getNowDateTimeStr(), "제목1", "제목1", 11));
		articles.add(new Article(2, Util.getNowDateTimeStr(), Util.getNowDateTimeStr(), "제목2", "제목2", 22));
		articles.add(new Article(3, Util.getNowDateTimeStr(), Util.getNowDateTimeStr(), "제목3", "제목3", 33));
	}
}

class Member {
	int id;
	String regDate;
	String updateDate;
	String loginId;
	String loginPw;
	String name;

	Member(int id, String regDate, String updateDate, String loginId, String loginPw, String name) {
		this.id = id;
		this.regDate = regDate;
		this.updateDate = updateDate;
		this.loginId = loginId;
		this.loginPw = loginPw;
		this.name = name;
	}
}

class Article {
	int id;
	String regDate;
	String updateDate;
	String title;
	String body;

	int hit;

	Article(int id, String regDate, String updateDate, String title, String body) {
		this(id, regDate, updateDate, title, body, 0);
	}

	Article(int id, String regDate, String updateDate, String title, String body, int hit) {
		this.id = id;
		this.regDate = regDate;
		this.updateDate = updateDate;
		this.title = title;
		this.body = body;
		this.hit = hit;
	}
}
package com.KoreaIT.java.AM;

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

public class Main {
	static List<Article> articles = new ArrayList<>();
	static List<Member> members = new ArrayList<>();

	public static void main(String[] args) {
		System.out.println("==프로그램 시작==");

		makeTestData();

		Scanner sc = new Scanner(System.in);

		int lastArticleId = 3;
		int lastMemberId = 0;

		while (true) {

			System.out.print("명령어 > ");
			String command = sc.nextLine().trim();

			if (command.length() == 0) {
				System.out.println("명령어를 입력해주세요");
				continue;
			}

			if (command.equals("exit")) {
				break;
			}

			if (command.equals("member join")) {
				int id = lastMemberId + 1;
				String regDate = Util.getNowDateTimeStr();
				String loginId = null;
				while (true) {
					System.out.print("로그인 아이디 : ");
					loginId = sc.nextLine();

					if (isJoinableLoginId(loginId) == false) {
						System.out.println("이미 사용중인 아이디입니다");
						continue;
					}

					break;

				}
				System.out.print("로그인 비밀번호 : ");
				String loginPw = sc.nextLine();
				System.out.print("로그인 비밀번호 확인: ");
				String loginPwConfirm = sc.nextLine();
				System.out.print("이름 : ");
				String name = sc.nextLine();

				Member member = new Member(id, regDate, regDate, loginId, loginPw, name);
				members.add(member);

				System.out.printf("%d번 회원이 가입되었습니다\n", id);
				lastMemberId++;

			} else if (command.equals("article write")) {
				int id = lastArticleId + 1;
				System.out.print("제목 : ");
				String regDate = Util.getNowDateTimeStr();
				String title = sc.nextLine();
				System.out.print("내용 : ");
				String body = sc.nextLine();

				Article article = new Article(id, regDate, regDate, title, body);
				articles.add(article);

				System.out.printf("%d번글이 생성되었습니다\n", id);
				lastArticleId++;

			} else if (command.startsWith("article list")) {
				if (articles.size() == 0) {
					System.out.println("게시글이 없습니다");
					continue;
				}

				String searchKeyword = command.substring("article list".length()).trim();

				List<Article> forPrintArticles = articles;

				if (searchKeyword.length() > 0) {
					System.out.println("searchKeyword : " + searchKeyword);
					forPrintArticles = new ArrayList<>();

					for (Article article : articles) {
						if (article.title.contains(searchKeyword)) {
							forPrintArticles.add(article);
						}
					}
					if (forPrintArticles.size() == 0) {
						System.out.println("검색 결과가 없습니다");
						continue;
					}
				}

				System.out.println(" 번호  //  제목    //  조회  ");
				for (int i = forPrintArticles.size() - 1; i >= 0; i--) {
					Article article = forPrintArticles.get(i);
					System.out.printf("  %d   //   %s   //   %d  \n", article.id, article.title, article.hit);
				}

			} else if (command.startsWith("article detail")) {

				String[] cmdDiv = command.split(" ");

				if (cmdDiv.length < 3) {
					System.out.println("명령어를 확인해주세요");
					continue;
				}

				int id = Integer.parseInt(cmdDiv[2]);

				Article foundArticle = getArticleById(id);

				if (foundArticle == null) {
					System.out.printf("%d번 게시물은 존재하지 않습니다\n", id);
					continue;
				}

				foundArticle.hit++;

				System.out.println("번호 : " + foundArticle.id);
				System.out.println("작성날짜 : " + foundArticle.regDate);
				System.out.println("수정날짜 : " + foundArticle.updateDate);
				System.out.println("제목 : " + foundArticle.title);
				System.out.println("내용 : " + foundArticle.body);
				System.out.println("조회 : " + foundArticle.hit);

			} else if (command.startsWith("article modify")) {

				String[] cmdDiv = command.split(" ");

				if (cmdDiv.length < 3) {
					System.out.println("명령어를 확인해주세요");
					continue;
				}

				int id = Integer.parseInt(cmdDiv[2]);

				Article foundArticle = getArticleById(id);

				if (foundArticle == null) {
					System.out.printf("%d번 게시물은 존재하지 않습니다\n", id);
					continue;
				}
				System.out.print("새 제목 : ");
				String updateDate = Util.getNowDateTimeStr();
				String newTitle = sc.nextLine();
				System.out.print("새 내용 : ");
				String newBody = sc.nextLine();

				foundArticle.title = newTitle;
				foundArticle.body = newBody;
				foundArticle.updateDate = updateDate;

				System.out.println(id + "번 글을 수정했습니다");

			} else if (command.startsWith("article delete")) {

				String[] cmdDiv = command.split(" ");

				if (cmdDiv.length < 3) {
					System.out.println("명령어를 확인해주세요");
					continue;
				}

				int id = Integer.parseInt(cmdDiv[2]);

				int foundIndex = getArticleIndexById(id);

				if (foundIndex == -1) {
					System.out.printf("%d번 게시물은 존재하지 않습니다\n", id);
					continue;
				}

				articles.remove(foundIndex);
				System.out.println(id + "번 글을 삭제했습니다");

			} else {
				System.out.println("존재하지 않는 명령어입니다");
			}
		}

		System.out.println("==프로그램 끝==");

		sc.close();
	}

	private static boolean isJoinableLoginId(String loginId) {
		int index = getMemberIndexByLoginId(loginId);

		if (index == -1) {
			return true;
		}

		return false;
	}

	private static int getMemberIndexByLoginId(String loginId) {
		int i = 0;
		for (Member member : members) {
			if (member.loginId.equals(loginId)) {
				return i;
			}
			i++;
		}
		return -1;
	}

	private static int getArticleIndexById(int id) {
		int i = 0;
		for (Article article : articles) {
			if (article.id == id) {
				return i;
			}
			i++;
		}
		return -1;
	}

	private static Article getArticleById(int id) {
		int index = getArticleIndexById(id);

		if (index != -1) {
			return articles.get(index);
		}

		return null;
	}

	private static void makeTestData() {
		System.out.println("테스트를 위한 데이터를 생성합니다");
		articles.add(new Article(1, Util.getNowDateTimeStr(), Util.getNowDateTimeStr(), "제목1", "제목1", 11));
		articles.add(new Article(2, Util.getNowDateTimeStr(), Util.getNowDateTimeStr(), "제목2", "제목2", 22));
		articles.add(new Article(3, Util.getNowDateTimeStr(), Util.getNowDateTimeStr(), "제목3", "제목3", 33));
	}
}

class Member {
	int id;
	String regDate;
	String updateDate;
	String loginId;
	String loginPw;
	String name;

	Member(int id, String regDate, String updateDate, String loginId, String loginPw, String name) {
		this.id = id;
		this.regDate = regDate;
		this.updateDate = updateDate;
		this.loginId = loginId;
		this.loginPw = loginPw;
		this.name = name;
	}
}

class Article {
	int id;
	String regDate;
	String updateDate;
	String title;
	String body;
	int hit;

	Article(int id, String regDate, String updateDate, String title, String body) {
		this(id, regDate, updateDate, title, body, 0);
	}

	Article(int id, String regDate, String updateDate, String title, String body, int hit) {
		this.id = id;
		this.regDate = regDate;
		this.updateDate = updateDate;
		this.title = title;
		this.body = body;
		this.hit = hit;
	}
}
package com.KoreaIT.java.AM;

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

public class Main {
	static List<Article> articles = new ArrayList<>();

	public static void main(String[] args) {
		System.out.println("==프로그램 시작==");

		makeTestData();

		Scanner sc = new Scanner(System.in);

		int lastArticleId = 3;

		while (true) {

			System.out.print("명령어 > ");
			String command = sc.nextLine().trim();

			if (command.length() == 0) {
				System.out.println("명령어를 입력해주세요");
				continue;
			}

			if (command.equals("exit")) {
				break;
			}

			if (command.startsWith("article list")) {
				if (articles.size() == 0) {
					System.out.println("게시글이 없습니다");
					continue;
				}

				String searchKeyword = command.substring("article list".length()).trim();

				List<Article> forPrintArticles = articles;

				if (searchKeyword.length() > 0) {
					System.out.println("searchKeyword : " + searchKeyword);
					forPrintArticles = new ArrayList<>();

					for (Article article : articles) {
						if (article.title.contains(searchKeyword)) {
							forPrintArticles.add(article);
						}
					}
					if (forPrintArticles.size() == 0) {
						System.out.println("검색 결과가 없습니다");
						continue;
					}
				}

				System.out.println(" 번호  //  제목    //  조회  ");
				for (int i = forPrintArticles.size() - 1; i >= 0; i--) {
					Article article = forPrintArticles.get(i);
					System.out.printf("  %d   //   %s   //   %d  \n", article.id, article.title, article.hit);
				}

			} else if (command.equals("article write")) {
				int id = lastArticleId + 1;
				System.out.print("제목 : ");
				String regDate = Util.getNowDateTimeStr();
				String title = sc.nextLine();
				System.out.print("내용 : ");
				String body = sc.nextLine();

				Article article = new Article(id, regDate, regDate, title, body);
				articles.add(article);

				System.out.printf("%d번글이 생성되었습니다\n", id);
				lastArticleId++;

			} else if (command.startsWith("article detail")) {

				String[] cmdDiv = command.split(" ");

				if (cmdDiv.length < 3) {
					System.out.println("명령어를 확인해주세요");
					continue;
				}

				int id = Integer.parseInt(cmdDiv[2]);

				Article foundArticle = getArticleById(id);

				if (foundArticle == null) {
					System.out.printf("%d번 게시물은 존재하지 않습니다\n", id);
					continue;
				}

				foundArticle.hit++;

				System.out.println("번호 : " + foundArticle.id);
				System.out.println("작성날짜 : " + foundArticle.regDate);
				System.out.println("수정날짜 : " + foundArticle.updateDate);
				System.out.println("제목 : " + foundArticle.title);
				System.out.println("내용 : " + foundArticle.body);
				System.out.println("조회 : " + foundArticle.hit);

			} else if (command.startsWith("article modify")) {

				String[] cmdDiv = command.split(" ");

				if (cmdDiv.length < 3) {
					System.out.println("명령어를 확인해주세요");
					continue;
				}

				int id = Integer.parseInt(cmdDiv[2]);

				Article foundArticle = getArticleById(id);

				if (foundArticle == null) {
					System.out.printf("%d번 게시물은 존재하지 않습니다\n", id);
					continue;
				}
				System.out.print("새 제목 : ");
				String updateDate = Util.getNowDateTimeStr();
				String newTitle = sc.nextLine();
				System.out.print("새 내용 : ");
				String newBody = sc.nextLine();

				foundArticle.title = newTitle;
				foundArticle.body = newBody;
				foundArticle.updateDate = updateDate;

				System.out.println(id + "번 글을 수정했습니다");

			} else if (command.startsWith("article delete")) {

				String[] cmdDiv = command.split(" ");

				if (cmdDiv.length < 3) {
					System.out.println("명령어를 확인해주세요");
					continue;
				}

				int id = Integer.parseInt(cmdDiv[2]);

				int foundIndex = getArticleIndexById(id);

				if (foundIndex == -1) {
					System.out.printf("%d번 게시물은 존재하지 않습니다\n", id);
					continue;
				}

				articles.remove(foundIndex);
				System.out.println(id + "번 글을 삭제했습니다");

			} else {
				System.out.println("존재하지 않는 명령어입니다");
			}
		}

		System.out.println("==프로그램 끝==");

		sc.close();
	}

	private static int getArticleIndexById(int id) {
		int i = 0;
		for (Article article : articles) {
			if (article.id == id) {
				return i;
			}
			i++;
		}
		return -1;
	}

	private static Article getArticleById(int id) {
		int index = getArticleIndexById(id);

		if (index != -1) {
			return articles.get(index);
		}

		return null;
	}

	private static void makeTestData() {
		System.out.println("테스트를 위한 데이터를 생성합니다");
		articles.add(new Article(1, Util.getNowDateTimeStr(), Util.getNowDateTimeStr(), "제목1", "제목1", 11));
		articles.add(new Article(2, Util.getNowDateTimeStr(), Util.getNowDateTimeStr(), "제목2", "제목2", 22));
		articles.add(new Article(3, Util.getNowDateTimeStr(), Util.getNowDateTimeStr(), "제목3", "제목3", 33));
	}
}

class Article {
	int id;
	String regDate;
	String updateDate;
	String title;
	String body;
	int hit;

	Article(int id, String regDate, String updateDate, String title, String body) {
		this(id, regDate, updateDate, title, body, 0);
	}

	Article(int id, String regDate, String updateDate, String title, String body, int hit) {
		this.id = id;
		this.regDate = regDate;
		this.updateDate = updateDate;
		this.title = title;
		this.body = body;
		this.hit = hit;
	}
}
@import url(//fonts.googleapis.com/earlyaccess/notosanskr.css);
html {
  /* 영문이면 roboto가 적용되고, 한글이면 Noto Sans KR가 적용되도록 아래와 같은 순서로 배치 */
  font-family: "Roboto", "Noto Sans KR", sans-serif;
}

/* 노말라이즈 */
body, ul, li, h1 {
  margin:0;
  padding:0;
  list-style:none;
}

a {
  color:inherit;
  text-decoration:none;
}

label[for] {
  cursor:pointer;
  user-select:none;
}

/* 라이브러리 */
.block {
  display:block;
}

.inline-block {
  display:inline-block;
}

.absolute-left {
  position:absolute;
  left:0;
}

.absolute-right {
  position:absolute;
  right:0;
}

.absolute-bottom {
  position:absolute;
  bottom:0;
}

.absolute-top {
  position:absolute;
  top:0;
}

.absolute-center {
  position:absolute;
  left:50%;
  transform:translateX(-50%);
}

.absolute-middle {
  position:absolute;
  top:50%;
  transform:translateY(-50%);
}

.absolute-middle.absolute-center {
  position:absolute;
  top:50%;
  left:50%;
  transform:translateX(-50%) translateY(-50%);
}

.relative {
  position:relative;
}

.cell {
  float:left;
  box-sizing:border-box;
}

.cell-right {
  float:right;
  box-sizing:border-box;
}

.row::after {
  content:"";
  display:block;
  clear:both;
}

.clear-both {
  clear:both;
}

.img-box > img {
  width:100%;
  display:block;
}

.con {
  margin-left:auto;
  margin-right:auto;
}

.margin-0-auto {
  margin-left:auto;
  margin-right:auto;
}

.text-align-center {
  text-align:center;
}

.text-align-right {
  text-align:right;
}

.line-height-0 {
  line-height:0;
}

.line-height-0 > * {
  line-height:normal;
}

.width-30px {
  width:30px;
}

.width-35px {
  width:35px;
}

.width-40px {
  width:35px;
}

.width-45px {
  width:35px;
}

.width-50px {
  width:50px;
}

.width-80px {
  width:80px;
}

.width-100px {
  width:100px;
}

.width-100p {
  width:100%;
}

.width-60p {
  width:60%;
}

.width-55p {
  width:55%;
}

.width-50p {
  width:50%;
}

.width-45p {
  width:45%;
}

.width-40p {
  width:40%;
}

.width-30p {
  width:30%;
}

.width-35p {
  width:35%;
}

.width-100p-except-30px {
  width:calc(100% - 30px);
}

.width-100p-except-35px {
  width:calc(100% - 35px);
}

.width-100p-except-40px {
  width:calc(100% - 40px);
}

.width-100p-except-50px {
  width:calc(100% - 50px);
}

.width-100p-except-80px {
  width:calc(100% - 80px);
}

.width-100p-except-100px {
  width:calc(100% - 100px);
}

.height-100p {
  height:100%;
}

.height-50p {
  height:50%;
}

.border-box {
  box-sizing:border-box;
}

.font-size-dot-8rem {
  font-size:.8rem;
}

.table-row {
  display:table;
}

.table-row.row::after {
  display:inline;
  clear:non;
}

.table-row > .cell {
  float:none;
  display:table-cell;
}

.border-red {
  border:10px solid red;
}

.border-green {
  border:10px solid green;
}

.border-blue {
  border:10px solid blue;
}

.border-gold {
  border:10px solid gold;
}

.border-pink {
  border:10px solid pink;
}

/* 라이브러리 - flex */
* > .flex {
  display:flex;
}

* > .flex-grow-1 {
  flex-grow:1;
}

* > .flex-jc-c {
  justify-content:center;
}

* > .flex-jc-s {
  justify-content:flex-start;
}

* > .flex-jc-e {
  justify-content:flex-end;
}

* > .flex-jc-sb {
  justify-content:space-between;
}

* > .flex-jc-sa {
  justify-content:space-around;
}

* > .flex-ai-c {
  align-items:center;
}

* > .flex-ai-s {
  align-items:flex-start;
}

* > .flex-ai-e {
  align-items:flex-end;
}

* > .flex-as-s {
  align-self:stretch;
}

* > .flex-as-c {
  align-self:center;
}

* > .flex-as-s {
  align-self:flex-start;
}

* > .flex-as-e {
  align-self:flex-end;
}

* > .flex-column-nowrap {
  flex-flow:column nowrap;
}

* > .flex-column-wrap {
  flex-flow:column wrap;
}

* > .flex-row-wrap {
  flex-flow:row wrap;
}

.flex-ch-basis-0 > * {
  flex-basis:0;
}

* > .flex-1-0-0 {
  flex:1 0 0;
}

* > .bg-red{
  background-color: red;
}

/* 커스텀 */

/* 고정형 .con 시작 */
.con-min-width {
  min-width:1370px;
}

.con {
  width:1370px;
}
/* 고정형 .con 끝 */

/* 반응형 타입 1 .con 시작 */
/*
.con {
  max-width:1370px;
}
*/
/* 반응형 타입 1 .con 끝 */

/* 반응형 타입 2(넓을때만 반응형) .con 시작 */
/*
.con-min-width {
  min-width:1370px;
}

.con {
  margin-left:50px;
  margin-right:50px;
}
*/
/* 반응형 타입 2(넓을때만 반응형) .con 끝 */​
<!-- 유용한 링크 -->
<!-- cdnsj : https://cdnjs.com/ -->
<!-- 폰트어썸 아이콘 리스트 : https://fontawesome.com/icons?d=gallery&m=free -->

<!-- 구글 폰트 불러오기 -->
<!-- rotobo(400/700/900), notosanskr(400/600/900) -->
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans+KR:wght@400;700;900&family=Roboto:wght@400;700;900&display=swap" rel="stylesheet">

<!-- 폰트어썸 불러오기 -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.2.1/css/all.min.css">

<!-- 제이쿼리 불러오기 -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.1/jquery.min.js"></script>

## 정렬 
  - 특정 컬럼을 지정해 그 컬럼의 값으로 행을 정렬.
    - order by 컬럼 asc/desc
        - asc : 오름차순
        - desc : 내림차순
        
        - Products 테이블에서 가격(Price)으로 오름차순, 제품번호(ProductId)로 내림차순 정렬하기
        ```
        select *
        from Products
        order by Price ASC, ProductID DESC;
        ```

## 별명 
  - 특정 컬럼을 새로운 별명을 붙여 사용. 주로 연산이나 함수를 통해 새로 나온 컬럼에 붙인다.
    - 컬럼 as 별명
    
    - Products 테이블에서 ProductId, SupplierId, CategoryId를 더한 값으로 새로운 컬럼을 만들고 컬럼 이름을 NewId로 정하기
    ```
    SELECT ProductId, SupplierId, CategoryId, ProductId + SupplierId + CategoryId as NewId FROM Products;
    ```

## 사칙연산 
  - +, *, /, - 
    - 숫자 + 숫자 == 산술 연산
    - 문자 + 숫자 == 문자는 0 취급
    - 컬럼1 + 컬럼2 == 컬럼의 모든 행이 연산.
    
    - 사칙 연산 예제
    ```
    SELECT 10 + 20;
    SELECT 10 * 20;
    SELECT 10 / 20;
    SELECT 10 - 20;
    ```

## 비교연산 
  - >, <, =, !=
    - 결과는 1(참, TRUE), 0(거짓, FALSE)
    - 비교 연산 예제
    ```
    SELECT 10 = 20;
    SELECT 10 != 20;
    SELECT 10 > 20;
    SELECT 10 < 20;
    SELECT 10 >= 20;
    SELECT 10 <= 20;
    ```

## 논리연산 
  - and, or 
    - and : 조건이 여러개 일 때 모두 만족해야 맞다고 보는 연산
    - or : 조건이 여러개일 때 하나라도 만족하면 맞다고 보는 연산
    
    - Customers 테이블에서 CustomerId값이 10 이상이고 CustomerId값이 20 이하인 행만 조회
    ```
    SELECT * 
    FROM Customers
    where CustomerID >= 10 
    and CustomerId <= 20;
    ```
    
    - Customers 테이블에서 CustomerId값이 20 이하인것 + CustomerId값이 80이상인 행을 모두 조회
    ```
    SELECT * 
    FROM Customers
    where CustomerID <= 20 
    or CustomerId >= 80;
    ```
    
    - Customers 테이블에서 CustomerId갑이 20 이하인 것  + CustomerId값이 80이상인 모든 컬럼 중에서 city가 'London'인 행을 조회
    ```
    SELECT * 
    FROM Customers
    where (CustomerID <= 20 
    or CustomerId >= 80)
    and city = 'London';
    ```

## 사잇값 
  - 컬럼 between A and B 
    - 컬럼값이 A와 B 사이인 것만 조회
    - Customers 테이블에서 CustomerId값이 10과 20 사이인 행을 조회
    ```
    SELECT * 
    FROM Customers
    where CustomerID BETWEEN 10 AND 20;
    ```

## 포함 
- 컬럼 in (A, B, C ...)
  - 컬럼값이 A,B,C 인것을 모두 조회
  - Customers 테이블에서 city 값에 'London', 'Berlin', 'Madrid' 중 하나라도 포함하는 행을 모두 조회
    ```
    SELECT * 
    FROM Customers
    WHERE City in ('London', 'Berlin', 'Madrid');
    ```

 

 

## LIKE, NOT LIKE
  - 특정 문자로 시작여부, 끝나는지 여부, 포함하는지 여부
  - 찾고자하는 문자열을 %기호와 조합해서 사용. 여기서 %는 나머지 문자를 의미
    - 'A%' : A로 시작하는 문자열
    - '%A' : A로 끝나는 문자열
    - '%A%' : A를 포함하는 문자열
    
    - Employees 테이블에서 LastName이 D로 시작하는 행만 조회
    ```
    SELECT * FROM Employees
    where LastName like 'D%';
    ```
    
    - Employees 테이블에서 LastName이 D로 시작하지 않는 행만 조회
    ```
    SELECT * FROM Employees
    where LastName not like 'D%';
    ```
    
## CEIL, ROUND, FLOOR
  - 소수점을 올림, 반올림, 버림
    - CEIL() : 올림
    - ROUND() : 반올림
    - FLOOR() : 버림
    
  - 1.2를 반올림
  ```
  SELECT ROUND(1.2); 
  ```
  - Products 테이블의 Price 컬럼값들을 반올림한다.
  ```
  SELECT ROUND(Price) FROM Products;
  ```
  
## AVG, MAX, MIN, SUM, COUNT
  - AVG(컬럼) : 컬럼의 모든 행의 평균값 구하기
  - MAX(컬럼) : 컬럼의 모든 행중 최대값 구하기
  - MIN(컬럼) : 컬럼의 모든 행중 최소값 구하기
  - SUM(컬럼) : 컬럼의 모든 행의 평균값 구하기
  - COUNT(컬럼) : 컬럼의 모든 행의 개수를 구하기 (NULL값은 카운팅에서 제외됨)
  
    - Categories 테이블에서 CategoryName 컬럼의 모든 행의 개수를 구하기.
    ```
    SELECT count(CategoryName) FROM Categories;
    ```
## CONCAT(문자1, 문자2, 문자3 ...)
  - 문자들을 이어 붙여줌.
  
  - 문자열 'taejin'과 'cha'를 이어 붙이기
  ```
   select concat('taejin', ' ','cha') as name;
   
  ```
  
  - Employees 테이블의 LastName과 FirstName을 이어 붙여 FullName이라는 새로운 컬럼으로 만들기
  ```
  SELECT EmployeeId, BirthDate, Photo, Notes, concat(LastName, ' ', FirstName) as FullName FROM Employees;
  ```
  
## SUBSTR(대상문자, 시작위치, 자르는길이)
  - 문자열을 잘라줌
  
  - 문자열 'taejincha'를 1번째 문자부터 6개 짜르기
  ```
  select substr('taejincha', 1, 6) as fisrtName;
  ```
  
  - Employees 테이블에서 BirthDate 컬럼의 모든 값을 1번째 문자부터 4개 짜르기(년도만 나오게 하기)
  ```
  SELECT substr(BirthDate, 1, 4) as `year` FROM Employees
  ```

## REPLACE(대상문자(컬럼), 문자열1, 문자열2)
  - 대상 문자(컬럼)에 문자열1인 부분을 찾아 문자열2로 치환해주기.
  
    - Customers 테이블의 city 컬럼의 값에서 B문자를 찾아 b로 바꾸기
    ```
    SELECT replace(city, 'B', 'b') FROM Customers;
    ```
    
## CURDATE(), NOW()
  - 오늘날짜 구하기
    - CURDATE : 연월일
    - NOW : 연월일 시분초
    
## ADDDATE(기준날짜, interval n day), SUBDATE()
  - 기준날짜로 부터 n만큼의 거리(간격)
## DATE_DIFF(날짜1, 날짜2)
  - 날짜1과 날짜2의 차이를 구함
  ```
  select datediff('2022-03-21', '2021-03-21');
  ```

## DISTINCT
  - 조회 결과에서 중복되는 행을 제거한다.
  
  - Suppliers에서 Country를 중복제거해서 조회하기
  ```
    SELECT DISTINCT Country 
    FROM Suppliers
  ```

 

 

### 그룹핑
  - 그룹핑은 특정 컬럼을 기준으로 그룹을 나누어 모든 행을 하나의 그룹으로 편입시켜 그룹별로 집계를 할 때 사용.
  
  - 예를 들어 ~별 ~결과를 봐야한다고 하면 그룹핑해야 한다고 생각하면 된다.

  - ex )
    - 국가별 ~~ 석유 사용 현황 -> 국가로 그룹핑
    - 연령별 ~~ 투표참여율 -> 연령으로 그룹핑
    - 지역별 ~~ 초등학교 개수 -> 지역으로 그룹핑
    - 도시별 ~~ 평균 주택 가격 -> 도시로 그룹핑

  - Customer 테이블에서 국가별 회원 수 보기
    ```
    SELECT Country, COUNT(Country) 
    FROM Customers 
    GROUP BY Country
    
    ```

  - Customer 테이블에서 도시별 회원 수 보기
    ```
    SELECT Country, City, COUNT(City) 
    FROM Customers 
    GROUP BY Country, City
    
    ```
### HAVING
  - 일반적으로 select문은 from > where > group by > having > select > order by 순으로 실행된다.
  - where가 group by 보다 먼저 실행되기 때문에 group by 이후에 where로 조건을 따질 수 없다. 그래서 having을 사용한다.
  - Customers 테이블에서 회원수가 5이상인 국가만 보기
    ```
    SELECT *, country, count(*) cnt FROM Customers 
    group by country
    having cnt > 5
    ```

자바 스크립트 시작
+(라이브러리로 제이쿼리)

DOM의 개념
컴파일언어와 스크립트언어 란 무엇이고 장단점과 차이
제이쿼리 용어

this
find랑 child는 후손,자식과 비슷

작업할때 수시로 저장,새로 수행할 때마다 포크 눌러서 시점 저장(url 바꿔야함)

 

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>

<section>
    <button>버튼 001</button>
    <button>버튼 002</button>
    <button>버튼 003</button>
    <button>버튼 004</button>
    <button>버튼 005</button>
    <button>버튼 006</button>
    <button>버튼 007</button>
    <button>버튼 008</button>
    <button>버튼 009</button>
    <button>버튼 010</button>
    <button>버튼 011</button>
    <button>버튼 012</button>
    <button>버튼 013</button>
    <button>버튼 014</button>
    <button>버튼 015</button>
    <button>버튼 016</button>
    <button>버튼 017</button>
    <button>버튼 018</button>
    <button>버튼 019</button>
    <button>버튼 020</button>
    <button>버튼 021</button>
    <button>버튼 022</button>
    <button>버튼 023</button>
    <button>버튼 024</button>
    <button>버튼 025</button>
    <button>버튼 026</button>
    <button>버튼 027</button>
    <button>버튼 028</button>
    <button>버튼 029</button>
    <button>버튼 030</button>
    <button>버튼 031</button>
    <button>버튼 032</button>
    <button>버튼 033</button>
    <button>버튼 034</button>
    <button>버튼 035</button>
    <button>버튼 036</button>
    <button>버튼 037</button>
    <button>버튼 038</button>
    <button>버튼 039</button>
    <button>버튼 040</button>
    <button>버튼 041</button>
    <button>버튼 042</button>
    <button>버튼 043</button>
    <button>버튼 044</button>
    <button>버튼 045</button>
    <button>버튼 046</button>
    <button>버튼 047</button>
    <button>버튼 048</button>
    <button>버튼 049</button>
    <button>버튼 050</button>
    <button>버튼 051</button>
    <button>버튼 052</button>
    <button>버튼 053</button>
    <button>버튼 054</button>
    <button>버튼 055</button>
    <button>버튼 056</button>
    <button>버튼 057</button>
    <button>버튼 058</button>
    <button>버튼 059</button>
    <button>버튼 060</button>
    <button>버튼 061</button>
    <button>버튼 062</button>
    <button>버튼 063</button>
    <button>버튼 064</button>
    <button>버튼 065</button>
    <button>버튼 066</button>
    <button>버튼 067</button>
    <button>버튼 068</button>
    <button>버튼 069</button>
    <button>버튼 070</button>
    <button>버튼 071</button>
    <button>버튼 072</button>
    <button>버튼 073</button>
    <button>버튼 074</button>
    <button>버튼 075</button>
    <button>버튼 076</button>
    <button>버튼 077</button>
    <button>버튼 078</button>
    <button>버튼 079</button>
    <button>버튼 080</button>
    <button>버튼 081</button>
    <button>버튼 082</button>
    <button>버튼 083</button>
    <button>버튼 084</button>
    <button>버튼 085</button>
    <button>버튼 086</button>
    <button>버튼 087</button>
    <button>버튼 088</button>
    <button>버튼 089</button>
    <button>버튼 090</button>
    <button>버튼 091</button>
    <button>버튼 092</button>
    <button>버튼 093</button>
    <button>버튼 094</button>
    <button>버튼 095</button>
    <button>버튼 096</button>
    <button>버튼 097</button>
    <button>버튼 098</button>
    <button>버튼 099</button>
    <button>버튼 100</button>
</section>

 

function a() {
    $('body').css('background-color', 'blue');
};

$('section > button:nth-child(2n + 1)').click(a);

var b = function () {
    $('body').css('background-color', 'red');
};

$('section > button:nth-child(2n)').click(b);

http://www.tcpschool.com/javascript/intro 자바스크립트 기초 

+ Recent posts