IT/DBMS

[MySQL/MariaDB] GROUP_CONCAT() 간단 사용법(feat. 문자열 붙이기)

알 수 없는 사용자 2022. 11. 22.
반응형

목차

     

    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를 원하는 필드로 해주면 아래처럼 나온다.

    반응형

    댓글