level 3. 야근 지수

|

출처

문제

야근 지수 회사원인 수민이는 많은 일이 쌓여 있습니다. 수민이는 야근을 최소화하기 위해 남은 일의 작업량을 숫자로 메기고, 일에 대한 야근 지수를 줄이기로 결정했습니다. 야근 지수는 남은 일의 작업량을 제곱하여 더한 값을 의미합니다. 수민이는 1시간 동안 남은 일 중 하나를 골라 작업량 1만큼 처리할 수 있습니다. 수민이의 퇴근까지 남은 N 시간과 각 일에 대한 작업량이 있을 때, noOvertime 함수를 제작하여 수민이의 야근 지수를 최소화 한 결과를 출력해 주세요. 예를 들어, N=4 일 때, 남은 일의 작업량이 [4, 3, 3] 이라면 야근 지수를 최소화하기 위해 일을 한 결과는 [2, 2, 2]가 되고 야근 지수는 22 + 22 + 22 = 12가 되어 12를 반환해 줍니다.

풀이

def noOvertime(n, works):
    if n >= sum(works):
        return 0
    while n > 0:
        works[works.index(max(works))] -= 1
        n -= 1
    result = sum([i*i for i in works])
    # 야근 지수를 최소화 하였을 때의 야근 지수는 몇일까요?
    return result

배운점

  • map 함수를 사용하지 않고도 리스트의 각 값에 연산을 수행할 수 있다.
  • index(x) 함수는 리스트에 x라는 값이 있으면 x의 위치값을 리턴한다. 값이 없으면 ValueError가 발생한다.

MySQL 06. MySQL - Table (조회5 join)

|

생활코딩 - MySQL

여러개의 테이블 사용하기

  • 데이터의 규모가 커지면서 하나의 테이블로 정보를 수용하기가 어려워지면 테이블을 분활하고 테이블 간의 관계성을 부여한다.

예제 테이블 1

  • 예제 중 address는 distnace와 관련되어 있기 때문에 location이라는 별도의 테이블로 분할 할 수 있다.
DROP TABLE IF EXISTS `student`;
CREATE TABLE `student` (
  `id` tinyint(4) NOT NULL,
  `name` char(4) NOT NULL,
  `sex` enum('남자','여자') NOT NULL,
  `address` varchar(50) NOT NULL,
  `distance` INT NOT NULL,
  `birthday` datetime NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

INSERT INTO `student` VALUES (2, '박재숙', '남자', '서울',  10, '1985-10-26 00:00:00');
INSERT INTO `student` VALUES (1, '이숙경', '여자', '청주', 200, '1982-11-16 00:00:00');
INSERT INTO `student` VALUES (3, '백태호', '남자', '경주', 350, '1989-2-10 00:00:00');
INSERT INTO `student` VALUES (4, '김경훈', '남자', '제천', 190, '1979-11-4 00:00:00');
INSERT INTO `student` VALUES (8, '김정인', '남자', '제주', 400, '1990-10-1 00:00:00');
INSERT INTO `student` VALUES (6, '김경진', '여자', '제주', 400, '1985-1-1 00:00:00');
INSERT INTO `student` VALUES (7, '박경호', '남자', '영동', 310, '1981-2-3 00:00:00');

예제 테이블 2

  • address, distance를 묶어서 별도의 테이블(location)로 만든다.
# student 테이블
DROP TABLE IF EXISTS `student`;
CREATE TABLE `student` (
  `id` tinyint(4) NOT NULL,
  `name` char(4) NOT NULL,
  `sex` enum('남자','여자') NOT NULL,
  `location_id` tinyint(4) NOT NULL,
  `birthday` datetime NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;


# location 테이블
DROP TABLE IF EXISTS `location`;
CREATE TABLE `location` (
`id`  tinyint UNSIGNED NOT NULL AUTO_INCREMENT ,
`name`  varchar(20) NOT NULL ,
`distance`  tinyint UNSIGNED NOT NULL ,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;;
INSERT INTO `location` VALUES (1, '서울', 10);
INSERT INTO `location` VALUES (2, '청주', 200);
INSERT INTO `location` VALUES (3, '경주', 255);
INSERT INTO `location` VALUES (4, '제천', 190);
INSERT INTO `location` VALUES (5, '대전', 200);
INSERT INTO `location` VALUES (6, '제주', 255);
INSERT INTO `location` VALUES (7, '영동', 255);
INSERT INTO `location` VALUES (8, '광주', 255);
INSERT INTO `student` VALUES (1, '이숙경', '여자', 1, '1982-11-16 00:00:00');
INSERT INTO `student` VALUES (2, '박재숙', '남자', 2, '1985-10-26 00:00:00');
INSERT INTO `student` VALUES (3, '백태호', '남자', 3, '1989-2-10 00:00:00');
INSERT INTO `student` VALUES (4, '김경훈', '남자', 4, '1979-11-4 00:00:00');
INSERT INTO `student` VALUES (6, '김경진', '여자', 5, '1985-1-1 00:00:00');
INSERT INTO `student` VALUES (7, '박경호', '남자', 6, '1981-2-3 00:00:00');
INSERT INTO `student` VALUES (8, '김정인', '남자', 5, '1990-10-1 00:00:00');

join

테이블간의 관계성에 따라서 복수의 테이블을 결합, 하나의 테이블인 것 처럼 결과를 출력

join의 종류

  • OUTTER JOIN : 매칭되는 행이 없어도 결과를 가져오고, 매칭되는 행이 없는 경우 NULL로 표시
    • LEFT JOIN : 왼쪽에 있는 테이블을 기준으로 오른쪽에 있는 테이블의 데이터를 가져온다.
    • RIGHT JOIN : 오른쪽에 있는 테이블을 기준으로 왼쪽에 있는 테이블의 데이터를 가져온다.
  • INNER JOIN : 매칭되는 행이 있는 경우만 표시한다.

LEFT JOIN

  • 가장 많이 사용되는 조인의 형태
  • AS : alias 의 약자
  • 문법 : 기준 테이블 AS 별명 LEFT JOIN 결합할 테이블 AS 별명 ON 결합기준
SELECT s.name, s.location_id, l.name AS address, l.distance  FROM student AS s LEFT JOIN location AS l ON s.location_id = l.id;

OUTTER JOIN과 INNER JOIN의 차이

  • location 테이블에서 제주를 삭제 후 OUTTER JOIN(LEFT JOIN)과 INNER JOIN의 차이를 비교
# location 테이블에서 제주 레코드 삭제
DELETE FROM location WHERE name='제주';

# LEFT JOIN
SELECT s.name, s.location_id, l.name AS address, l.distance  FROM student AS s LEFT JOIN location AS l ON s.location_id = l.id;

+-----------+--------+---------+----------+
| name      | sex    | address | distance |
+-----------+--------+---------+----------+
| 이숙경      | 여자    | 서울     |       10 |
| 박재숙      | 남자    | 청주     |      200 |
| 백태호      | 남자    | 경주     |      255 |
| 김경훈      | 남자    | 제천     |      190 |
| 김경진      | 여자    | 대전     |      200 |
| 박경호      | 남자    | NULL    |     NULL |
| 김정인      | 남자    | 대전     |      200 |
+-----------+--------+---------+----------+

# INNER JOIN
SELECT s.name, s.location_id, l.name AS address, l.distance  FROM student AS s INNER JOIN location AS l ON s.location_id = l.id;

+-----------+--------+---------+----------+
| name      | sex    | address | distance |
+-----------+--------+---------+----------+
| 이숙경      | 여자    | 서울     |       10 |
| 박재숙      | 남자    | 청주     |      200 |
| 백태호      | 남자    | 경주     |      255 |
| 김경훈      | 남자    | 제천     |      190 |
| 김경진      | 여자    | 대전     |      200 |
| 김정인      | 남자    | 대전     |      200 |
+-----------+--------+---------+----------+

MySQL 06. MySQL - Table (조회4 index, where)

|

생활코딩 - MySQL

index

  • 색인, 조회할 때 원하는 행을 빠르게 찾을 수 있게 준비해둔 데이터
  • 데이터베이스의 성능이 중요한 경우 인덱스 설계가 중요하다.

인덱스 정의 방법

  • 자주 조회되는 칼럼에 적용
  • 조회 시 오랜시간을 소모하는 컬럼에 적용
  • 데이터가 긴 경우 인덱스를 사용하지 않는다.

인덱스의 종류

  • primary key: 중복되지 않는 유일한 키
  • unique key : 중복을 허용하지 않는 유일한 키
  • normal key : 중복을 허용하는 인덱스
  • foreign key : 다른 테이블과의 관계성을 부여하는 키
  • full text : 자연어 검색, myisam에서만 지원

예제에서 사용한 테이블

DROP TABLE IF EXISTS `student`;
CREATE TABLE `student` (
  `id` tinyint(4) NOT NULL AUTO_INCREMENT,
  `name` char(4) NOT NULL,
  `address` varchar(50) NOT NULL,
  `department` enum('국문과','영문과','컴퓨터공학과','전자공학과','물리학과') NOT NULL,
  `introduction` text NOT NULL,
  `number` char(255) NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `idx_number` (`number`) USING BTREE,
  KEY `idx_department` (`department`),
  KEY `idx_department_name` (`department`,`address`),
  FULLTEXT KEY `idx_introduction` (`introduction`)
) ENGINE=MyISAM AUTO_INCREMENT=9 DEFAULT CHARSET=utf8;

INSERT INTO `student` VALUES (1, '이숙경', '청주', '컴퓨터공학과', '저는 컴퓨터 공학과에 다닙니다. computer', '0212031');
INSERT INTO `student` VALUES (2, '박재숙', '서울', '영문과', '저는 영문과에 다닙니다.', '0512321');
INSERT INTO `student` VALUES (3, '백태호', '경주', '컴퓨터공학과', '저는 컴퓨터 공학과에 다니고 경주에서 왔습니다.', '0913134');
INSERT INTO `student` VALUES (4, '김경훈', '제천', '국문과', '제천이 고향이고 국문과에 다닙니다.', '9813413');
INSERT INTO `student` VALUES (6, '김경진', '제주', '국문과', '이번에 국문과에 입학한 김경진이라고 합니다. 제주에서 왔어요.', '0534543');
INSERT INTO `student` VALUES (7, '박경호', '제주', '국문과', '박경호입니다. 잘 부탁드립니다.', '0134511');
INSERT INTO `student` VALUES (8, '김정인', '대전', '영문과', '김정인입니다. 대전에서 왔고, 영문과에 다닙니다.', '0034543');

primary key

  • 테이블 전체를 통틀어서 중복되지 않는 값을 지정해야 한다.
  • where 문을 이용해서 데이터를 조회할 때 가장 고속으로 데이터를 가져올 수 있다.
  • 테이블마다 딱 하나의 primary key를 가질 수 있다.
# 설정
PRIMARY KEY (`id`)

# 예시
SELECT * FROM student WHERE id=3;

unique key

  • 테이블 전체를 통틀어서 중복되지 않는 값을 지정해야 한다. (== primary key)
  • 고속으로 데이터를 가져올 수 있다.
  • 여러개의 unique key를 지정할 수 있다.
# 설정
UNIQUE KEY `idx_number` (`number`) USING BTREE

# 예시
SELECT * FROM student WHERE number=0534543;

normal key, 중복키

  • 중복을 허용한다.
  • primary, unique 보다 속도가 느리다.
  • 여러개의 키를 지정할 수 있다.
# 설정
KEY `idx_department` (`department`),
KEY `idx_department_name` (`department`,`address`)

# 예시
SELECT * FROM student WHERE department='국문과';
SELECT * FROM student WHERE department='국문과' AND address='제주';

Full Text

  • mysql의 기본설정(ft_min_word_len)이 4로 되어 있기 때문에 최소 4글자 이상을 입력하거나 이 값을 조정해야 한다.
  • mysql은 전문 검색 엔진이 아니기 때문에 한글 검색이 잘 안된다.
  • 전문검색엔진으로 lucene, sphinx 참고 (무료, 성능 좋음)
  • 스토리지 엔진 중 myisam에서만 사용가능
# 설정
ENGINE=MyISAM

# 예시
SELECT introduction, MATCH(introduction) AGAINST('영문과에') FROM student WHERE MATCH (introduction) AGAINST('영문과에');

MySQL 06. MySQL - Table (조회3 정렬 order by)

|

생활코딩 - MySQL

정렬 (order by)

  • 지정된 칼럼을 기준으로 행을 정렬

문법

  • DESC (descending order) : 내림차순
  • ASC (ascending order) : 오름차순
SELECT * FROM 테이블명 ORDER BY 정렬의 기준으로 사용할 열 [DESC | ASC]

예제

대상 테이블

DROP TABLE IF EXISTS `student`;
CREATE TABLE `student` (
  `id` tinyint(4) NOT NULL,
  `name` char(4) NOT NULL,
  `sex` enum('남자','여자') NOT NULL,
  `address` varchar(50) NOT NULL,
  `distance` INT NOT NULL,
  `birthday` datetime NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

INSERT INTO `student` VALUES (2, '박재숙', '남자', '서울',  10, '1985-10-26 00:00:00');
INSERT INTO `student` VALUES (1, '이숙경', '여자', '청주', 200, '1982-11-16 00:00:00');
INSERT INTO `student` VALUES (3, '백태호', '남자', '경주', 350, '1989-2-10 00:00:00');
INSERT INTO `student` VALUES (4, '김경훈', '남자', '제천', 190, '1979-11-4 00:00:00');
INSERT INTO `student` VALUES (8, '김정인', '남자', '대전', 200, '1990-10-1 00:00:00');
INSERT INTO `student` VALUES (6, '김경진', '여자', '제주', 400, '1985-1-1 00:00:00');
INSERT INTO `student` VALUES (7, '박경호', '남자', '영동', 310, '1981-2-3 00:00:00');

정렬 order by 예시

# distance 내림차순으로 테이블 정렬
select * from student order by distance desc;

# distance 내림차순, address 오름차순으로 테이블 정렬
select * from student order by distance desc, address asc;

MySQL 06. MySQL - Table (조회2 그룹핑 group by)

|

생활코딩 - MySQL

그룹핑 (group by)

  • 특정 칼럼을 기준으로 데이터를 그룹핑한다.
  • 그룹이라고 하는 것은 여러개의 데이터가 어떻게 구성되어 있는지 원자화 시키는 것이다.
  • 각각의 그룹핑된 컬럼을 기준으로 특정한 다른 컬럼의 합계, 평균 등의 작업도 가능하다.

문법

SELECT * FROM 테이블명 GROUP BY 그룹핑 할 기준 칼럼명

예제

대상 테이블

DROP TABLE IF EXISTS `student`;
CREATE TABLE `student` (
  `id` tinyint(4) NOT NULL,
  `name` char(4) NOT NULL,
  `sex` enum('남자','여자') NOT NULL,
  `address` varchar(50) NOT NULL,
  `distance` INT NOT NULL,
  `birthday` datetime NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;


INSERT INTO `student` VALUES (2, '박재숙', '남자', '서울',  10, '1985-10-26 00:00:00');
INSERT INTO `student` VALUES (1, '이숙경', '여자', '청주', 200, '1982-11-16 00:00:00');
INSERT INTO `student` VALUES (3, '백태호', '남자', '경주', 350, '1989-2-10 00:00:00');
INSERT INTO `student` VALUES (4, '김경훈', '남자', '제천', 190, '1979-11-4 00:00:00');
INSERT INTO `student` VALUES (8, '김정인', '남자', '대전', 200, '1990-10-1 00:00:00');
INSERT INTO `student` VALUES (6, '김경진', '여자', '제주', 400, '1985-1-1 00:00:00');
INSERT INTO `student` VALUES (7, '박경호', '남자', '영동', 310, '1981-2-3 00:00:00');

그룹핑 group by 예시

select sex from student group by sex;
# 결과값
+--------+
| sex    |
+--------+
| 남자    |
| 여자    |
+--------+

select sex,sum(distance), avg(distance) from student group by sex;
# 결과값
+--------+---------------+---------------+
| sex    | sum(distance) | avg(distance) |
+--------+---------------+---------------+
| 남자    |          1060 |      212.0000 |
| 여자    |           600 |      300.0000 |
+--------+---------------+---------------+