MySQL 에서 JOIN에 대해 알아보도록 하겠습니다.


0. JOIN 개요

SQL JOIN 이라고 검색하면 나오는 유명한(?) 그림 입니다. 일단 이 그림만 보아도 JOIN에 대한 개념을 어느정도 잡을 수 있습니다.


1. 테스트할 데이터 준비

CREATE TABLE IF NOT EXISTS `member` (
  `idx` int(11) NOT NULL AUTO_INCREMENT,
  `email` varchar(50) NOT NULL,
  `username` varchar(50) NOT NULL,
  PRIMARY KEY (`idx`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;

INSERT INTO `member` (`idx`, `email`, `username`) VALUES
	(1, '철수@초보끼리.com', '김철수'),
	(2, '영희@초보끼리.com', '이영희'),
	(3, '초보@초보끼리.com', '김초보');

CREATE TABLE IF NOT EXISTS `member_detail` (
  `member_idx` int(11) NOT NULL,
  `phone` varchar(50) NOT NULL,
  `nickname` varchar(50) NOT NULL,
  `thumbnail` varchar(50) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

INSERT INTO `member_detail` (`member_idx`, `phone`, `nickname`, `thumbnail`) VALUES
	(1, '01011121112', '철수철수', '철수.png'),
	(3, '01012341234', '초보', '초보.jpg');

CREATE TABLE IF NOT EXISTS `order_address` (
  `idx` int(11) NOT NULL AUTO_INCREMENT,
  `member_idx` int(11) NOT NULL,
  `addressee` varchar(50) NOT NULL COMMENT '수취인',
  `address` varchar(200) NOT NULL,
  `phone` varchar(50) NOT NULL,
  PRIMARY KEY (`idx`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;

INSERT INTO `order_address` (`idx`, `member_idx`, `addressee`, `address`, `phone`) VALUES
	(1, 1, '김철수', '서울시 강남구 타워펠리스 지하 4층', '01011121112'),
	(2, 1, '김철수 어머니', '서울시 강남구 삐까뻔적 오피스텔 2층 201호', '01012341234'),
	(3, 2, '김초보', '뉴욕시 마봉리 페리스 오피스텔 지하 2층', '01011112222'),
	(4, 10000, '비회원', '토쿄시 나루토군 라면이오이시 닌자아파트 5층 502호', '01011112222');


2. SELECT <select_list> FROM TableA A LEFT JOIN TableB B ON A.key = B.key

SELECT * FROM member AS M
LEFT JOIN member_detail AS MD ON M.idx = MD.member_idx

3. SELECT <select_list> FROM TableA A LEFT JOIN TableB B ON A.key = B.key WHERE B.key IS NULL

SELECT * FROM member AS M
LEFT JOIN member_detail AS MD ON M.idx = MD.member_idx
WHERE MD.member_idx IS NULL



4. SELECT <select_list> FROM TableA A RIGHT JOIN TableB B ON A.key = B.key 

SELECT * FROM member AS M
RIGHT JOIN order_address AS OA ON M.idx = OA.member_idx


5. SELECT <select_list> FROM TableA A RIGHT JOIN TableB B ON A.key = B.key WHERE A.key IS NULL

SELECT * FROM member AS M
RIGHT JOIN order_address AS OA ON M.idx = OA.member_idx
WHERE M.idx IS NULL


6. SELECT <select_list> FROM TableA A INNER JOIN TableB B ON A.key = B.key 

SELECT * FROM member AS M
INNER JOIN member_detail AS MD ON M.idx = MD.member_idx


7. SELECT <select_list> FROM TableA A FULL OUTER JOIN TableB B ON A.key = B.key 

SELECT * FROM member AS M
LEFT JOIN order_address AS OA ON M.idx = OA.member_idx
UNION
SELECT * FROM member AS M
RIGHT JOIN order_address AS OA ON M.idx = OA.member_idx


8. SELECT <select_list> FROM TableA A FULL OUTER JOIN TableB B ON A.key = B.key WHERE A.key IS NULL OR B.key IS NULL

SELECT * FROM (
SELECT M.*, OA.addressee, OA.member_idx, OA.address, OA.phone  FROM member AS M
LEFT JOIN order_address AS OA ON M.idx = OA.member_idx
UNION
SELECT M.*, OA.addressee, OA.member_idx,  OA.address, OA.phone  FROM member AS M
RIGHT JOIN order_address AS OA ON M.idx = OA.member_idx
) AS U
WHERE U.idx IS NULL OR U.member_idx IS NULL


MySQL에서 도메인에 값들의 갯수를 세어야 할 때가 있습니다. 그럴 때 사용할 수 있는 것이 SUM과 IF의 조합입니다.


1. 테스트할 데이터 준비



CREATE TABLE IF NOT EXISTS `count_test` (
`id` int(11) NOT NULL,
`state` enum('Y','N') NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

INSERT INTO `count_test` (`id`, `state`) VALUES
(1, 'Y'),
(2, 'Y'),
(3, 'Y'),
(4, 'Y'),
(5, 'N'),
(6, 'Y'),
(7, 'N'),
(8, 'Y'),
(9, 'Y'),
(10, 'N');



2. 갯수 세기(SUM, IF)


SELECT SUM(IF(state = "Y", 1, 0)) AS y_cnt, SUM(IF(state = "N", 1, 0)) AS n_cnt FROM count_test


스키마를 엑셀에 문서화 하고 싶을 때 다음과 같이 쿼리를 생성하여 csv 혹은 엑셀로 export하여 사용하면 된다.


SELECT 
TABLE_SCHEMA, 
TABLE_NAME, 
COLUMN_NAME, 
CONCAT(DATA_TYPE,'(',IFNULL(CHARACTER_MAXIMUM_LENGTH,IFNULL(NUMERIC_PRECISION,'')),')') TYPE, 
COLUMN_KEY,
IS_NULLABLE
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA NOT IN ('information_schema', 'performance_schema', 'mysql', 'isb_stg', 'isb_prd')
ORDER BY TABLE_SCHEMA, TABLE_NAME, ORDINAL_POSITION;

datetime 필드에서 날짜 혹은 시간만 SELECT 하려면 다음과 같이 하면 된다.

SELECT DATE_FORMAT("2016-04-08 11:12:14", '%Y-%m-%d') DATEONLY, 
            DATE_FORMAT("2016-04-08 11:12:14",'%H:%i:%s') TIMEONLY


날짜 별로 행의 갯수를 세야 할 때 다음과 같이 쿼리를 작성하면 된다.

SELECT DATE_FORMAT(날짜 필드, '%Y%m%d') AS date, count(*) AS cnt 
FROM 테이블 이름
GROUP BY DATE_FORMAT(날짜 필드, '%Y%m%d') ORDER BY date DESC;

특정 필드가 업데이트 될 때 트리거를 작동하게 해야 할 때가 있다.

그럴 때는 다음과 같이 트리거를 생성하면 된다.

CREATE  TRIGGER  tg_my_trigger AFTER UPDATE ON tbl_my_table
 FOR EACH ROW
BEGIN
if NEW.column1 <> OLD.column1
begin 
--작성
end
END

MySQL 에서 문자를 검색할 때 대소문자를 구분해야할 때가 있다. 그럴때 다음과 같이 하면 된다.

SELECT your_field FROM your_table_name WHERE BINARY(your_field) LIKE "%your search word%"

1. 테스트할 테이블 생성 코드

[그림 1-1] 테스트할 테이블 및 데이터


CREATE TABLE `tbl_condition_test` (
    `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
    `col1` INT(10) UNSIGNED NULL DEFAULT NULL,
    `col2` INT(10) UNSIGNED NULL DEFAULT NULL,
    PRIMARY KEY (`id`)
)
COLLATE='utf8_general_ci'
ENGINE=MyISAM

2. 샘플 데이터 삽입 코드

INSERT INTO `test` (`id`, `col1`, `col2`) VALUES (1, NULL, 11);
INSERT INTO `test` (`id`, `col1`, `col2`) VALUES (2, 2, 12);
INSERT INTO `test` (`id`, `col1`, `col2`) VALUES (3, 3, 13);
INSERT INTO `test` (`id`, `col1`, `col2`) VALUES (4, NULL, 14);
INSERT INTO `test` (`id`, `col1`, `col2`) VALUES (5, 5, 15);
INSERT INTO `test` (`id`, `col1`, `col2`) VALUES (6, 6, 21);
INSERT INTO `test` (`id`, `col1`, `col2`) VALUES (7, 7, 22);
INSERT INTO `test` (`id`, `col1`, `col2`) VALUES (8, 8, 23);
INSERT INTO `test` (`id`, `col1`, `col2`) VALUES (9, NULL, 24);
INSERT INTO `test` (`id`, `col1`, `col2`) VALUES (10, 10, 25);


3. 상황을 하나 예로 들어서 조건문을 어떻게 사용하는지 알아보려고 합니다.

[예시] 만약 col1 값이 NULL이면 col2 값을 선택하고 만약 col1값이 NULL이 아니면 col1값을 선택한다.

3-1) IF 이용하기

SELECT IF( col1 IS NULL, col2, col1) FROM tbl_condition_test

3-2) IFNULL 이용하기

SELECT IFNULL(col1, col2) FROM tbl_condition_test

3-3) CASE WHEN THEN ELSE END 이용하기 

여기에는 위 조건에 하나 더 추가하여 col1 값이 10이면 100을 선택한다로 해보겠습니다.

SELECT CASE WHEN col1 IS NULL THEN col2 
			WHEN col1 = 10 THEN 100 
			ELSE col1 END
FROM tbl_condition_test


+ Recent posts