IT/DataBase

[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๋ฅผ ์›ํ•˜๋Š” ํ•„๋“œ๋กœ ํ•ด์ฃผ๋ฉด ์•„๋ž˜์ฒ˜๋Ÿผ ๋‚˜์˜จ๋‹ค.

    ๋Œ“๊ธ€