목차
GROUP_CONCAT() 간단 사용법 😃
역시나 미래의 내가 보기위해 기록함
업무를 하다보면 특정 필드값을 아래처럼 가로로 붙여서 보여줘야 되는 경우도 있다.
데이터를 클라이언트에 반환 시 쿼리 2번 날릴 걸 1번 날리는게 좋기 때문에 아래처럼 붙이는 방법도 있다.
예를 들어 SNS 서비스에서 최종적으로 반환해야되는 데이터가 회원 정보 + 회원 등록한 해시태그 목록이라고 가정을 해보면 대략 아래와 같은 데이터가 반환되야 될 것이다.
회원일련번호, 회원아이디, 회원이름, 회원이메일, 기타 회원 정보, 그리고 해시태그
DB 테이블 구조 😗
DB 테이블은 아래와 같다.
동일한 테스트를 할 수 있도록 스크립트도 첨부한다.
script(DDL)
-- 회원 테이블
CREATE TABLE `member_220815_test` (
`mem_no` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '일련번호',
`mem_id` varchar(200) NOT NULL DEFAULT '' COMMENT '회원 아이디',
`password` varchar(100) NOT NULL COMMENT '비밀번호',
PRIMARY KEY (`mem_no`)
) ENGINE=InnoDB AUTO_INCREMENT=480 DEFAULT CHARSET=utf8mb4 COMMENT='회원'
-- 매핑 테이블
CREATE TABLE `member_220815_tag_220815_mapping` (
`mem_no` bigint(20) unsigned NOT NULL,
`tag_no` bigint(20) unsigned NOT NULL,
PRIMARY KEY (`mem_no`,`tag_no`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='회원_태그_매핑'
-- 해시태그 테이블
CREATE TABLE `tag_220815_test` (
`tag_no` bigint(20) NOT NULL,
`tag_name` varchar(50) DEFAULT NULL,
PRIMARY KEY (`tag_no`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='해시태그'
script(DML)
-- 회원 테이블 테스트 데이터
INSERT INTO member_220815_test
(mem_no, mem_id, password)
VALUES(5, 'test@gmail.com', 'bcb15f821479b4d5772bd0ca866c00ad5f926e3580720659cc80d39c9d09802a');
INSERT INTO member_220815_test
(mem_no, mem_id, password)
VALUES(10, 'test', 'bcb15f821479b4d5772bd0ca866c00ad5f926e3580720659cc80d39c9d09802a');
INSERT INTO member_220815_test
(mem_no, mem_id, password)
VALUES(11, 'test1', 'bcb15f821479b4d5772bd0ca866c00ad5f926e3580720659cc80d39c9d09802a');
INSERT INTO member_220815_test
(mem_no, mem_id, password)
VALUES(147, 'test4@naver.com', 'bcb15f821479b4d5772bd0ca866c00ad5f926e3580720659cc80d39c9d09802a');
INSERT INTO member_220815_test
(mem_no, mem_id, password)
VALUES(154, 'testasdf@naver.com', 'bcb15f821479b4d5772bd0ca866c00ad5f926e3580720659cc80d39c9d09802a');
INSERT INTO member_220815_test
(mem_no, mem_id, password)
VALUES(186, 'test1234@naver.com', 'bcb15f821479b4d5772bd0ca866c00ad5f926e3580720659cc80d39c9d09802a');
INSERT INTO member_220815_test
(mem_no, mem_id, password)
VALUES(197, 'test523@naver.com', 'bcb15f821479b4d5772bd0ca866c00ad5f926e3580720659cc80d39c9d09802a');
INSERT INTO member_220815_test
(mem_no, mem_id, password)
VALUES(271, 'test5@naver.com', 'bcb15f821479b4d5772bd0ca866c00ad5f926e3580720659cc80d39c9d09802a');
INSERT INTO member_220815_test
(mem_no, mem_id, password)
VALUES(459, 'test11111@naver.com', 'bcb15f821479b4d5772bd0ca866c00ad5f926e3580720659cc80d39c9d09802a');
-- 매핑 테이블 테스트 데이터
INSERT INTO member_220815_tag_220815_mapping
(mem_no, tag_no)
VALUES(5, 1);
INSERT INTO member_220815_tag_220815_mapping
(mem_no, tag_no)
VALUES(5, 2);
INSERT INTO member_220815_tag_220815_mapping
(mem_no, tag_no)
VALUES(5, 3);
INSERT INTO member_220815_tag_220815_mapping
(mem_no, tag_no)
VALUES(5, 4);
INSERT INTO member_220815_tag_220815_mapping
(mem_no, tag_no)
VALUES(10, 2);
INSERT INTO member_220815_tag_220815_mapping
(mem_no, tag_no)
VALUES(10, 5);
INSERT INTO member_220815_tag_220815_mapping
(mem_no, tag_no)
VALUES(10, 6);
INSERT INTO member_220815_tag_220815_mapping
(mem_no, tag_no)
VALUES(10, 7);
INSERT INTO member_220815_tag_220815_mapping
(mem_no, tag_no)
VALUES(10, 8);
INSERT INTO member_220815_tag_220815_mapping
(mem_no, tag_no)
VALUES(11, 3);
INSERT INTO member_220815_tag_220815_mapping
(mem_no, tag_no)
VALUES(147, 4);
INSERT INTO member_220815_tag_220815_mapping
(mem_no, tag_no)
VALUES(154, 5);
INSERT INTO member_220815_tag_220815_mapping
(mem_no, tag_no)
VALUES(186, 6);
INSERT INTO member_220815_tag_220815_mapping
(mem_no, tag_no)
VALUES(197, 7);
INSERT INTO member_220815_tag_220815_mapping
(mem_no, tag_no)
VALUES(271, 8);
INSERT INTO member_220815_tag_220815_mapping
(mem_no, tag_no)
VALUES(459, 9);
-- 해시태그 테이블 테스트 데이터
INSERT INTO tag_220815_test
(tag_no, tag_name)
VALUES(1, '재테크');
INSERT INTO tag_220815_test
(tag_no, tag_name)
VALUES(2, '건강');
INSERT INTO tag_220815_test
(tag_no, tag_name)
VALUES(3, '짠테크');
INSERT INTO tag_220815_test
(tag_no, tag_name)
VALUES(4, '소확행');
INSERT INTO tag_220815_test
(tag_no, tag_name)
VALUES(5, '욜로');
INSERT INTO tag_220815_test
(tag_no, tag_name)
VALUES(6, '풍경');
INSERT INTO tag_220815_test
(tag_no, tag_name)
VALUES(7, '카페');
INSERT INTO tag_220815_test
(tag_no, tag_name)
VALUES(8, '맛집');
INSERT INTO tag_220815_test
(tag_no, tag_name)
VALUES(9, '주식');
member 테이블과 tag_name은 N:M관계 이므로 중간에 매핑 테이블을 하나 두고 매핑 테이블은 각각 테이블의 pk(mem_no, tag_no)를 복합키로 가지고 member테이블과 tag_name 테이블에서 이를 참조해서 조회하고 매핑 테이블에는 중복값이 있다.(회원 한명이 여러개의 해시태그를 등록한 경우)
이 경우 member 테이블을 기준으로 단순하게 조인을 할 경우 아래처럼 5번과 10번 회원의 중복데이터가 나온다.(매핑 테이블에 5번과 10번이 중복이기에)
회원 한명에 대해서 해시태그가 여러개인 경우 아래처럼 표시를 하고 싶다.
GROUP_CONCAT()을 이용한 SQL 🤩
이 경우 아래처럼 쿼리를 질의하면 된다.(회원 테이블을 기준으로 매핑 테이블을 이용해서 태그명 조회하되 GROUP_CONCAT()으로 문자열을 붙여서 조회)
select a.*,
GROUP_CONCAT(c.tag_name) tag_name
from member_220815_test a left outer join member_220815_tag_220815_mapping b on a.mem_no = b.mem_no
left outer join tag_220815_test c on b.tag_no = c.tag_no
-- 테스트만 조회(테스트 환경에서 기존의 member테이블을 복사해와서 실데이터도 있기에 제외함)
where a.mem_id LIKE 'test%'
group by a.mem_no
;
GROUP_CONCAT() 사용 시 아래처럼 필드의 값을 한줄로 붙여서 보여준다.
문자열을 붙일 필드를 단순하게 GROUP_CONCAT()으로 실행 시 아래처럼 GROUP_CONCAT한 필드의 모든 데이터가 한줄로 붙어서 나온다.
이 때 GROUP BY를 원하는 필드로 해주면 아래처럼 나온다.
'IT > DBMS' 카테고리의 다른 글
[Cubrid]시스템 카탈로그(테이블, 컬럼 조회) (0) | 2022.11.22 |
---|---|
[MySQL/MariaDB] Column 'xx' in where clause is ambiguous 에러 (0) | 2022.11.22 |
[MySQL/MariaDB] merge(값이 있으면 update, 아니면 insert)(feat. ON DUPLICATE KEY UPDATE...) (0) | 2022.11.22 |
[Oracle]GROUP BY + 그룹함수(SUM, COUNT 등) (0) | 2022.11.19 |
[Oracle] ORA-12547 TNS lost contact/UDE-12547 error.. (0) | 2022.11.19 |
댓글