본문 바로가기
플랫폼엘 정리or해석

실무 다른 동료 SQL문 분석

by shulk 2024. 7. 11.

1.

<select id="getTagListWithConnectedItemCount" parameterType="Integer" resultType="TagVo">
            SELECT
                  TAG.IDX,
                  TAG.DEPTH_TYPE,
                  TAG.DEPTH1_IDX,
                  TAG.DEPTH2_IDX,
                  TAG.ITEM_ORDER,
                  TAG.TAG_NAME_KOR,
                  TAG.TAG_NAME_ENG,
                  TAG.IS_SHOW,
                  COUNT(EXHIBIT_TAG.IDX) AS CONNECTED_ITEM_COUNT,
                  TAG.REG_DTTM
            FROM
                TB_TAG TAG
                LEFT JOIN TB_EXHIBIT_TAG EXHIBIT_TAG ON EXHIBIT_TAG.TAG_IDX = TAG.IDX
            WHERE
                TAG.DEPTH_TYPE != 1
                  <if test="depth1_idx != null">
                        AND TAG.DEPTH1_IDX = #{depth1_idx}
                  </if>
            GROUP BY
                TAG.IDX, TAG.DEPTH_TYPE, TAG.DEPTH1_IDX, 
                TAG.DEPTH2_IDX, TAG.ITEM_ORDER, TAG.TAG_NAME_KOR, 
                TAG.TAG_NAME_ENG, TAG.IS_SHOW, TAG.REG_DTTM
            ORDER BY
                TAG.DEPTH1_IDX, TAG.DEPTH2_IDX, TAG.ITEM_ORDER;
      </select>

 

이렇게 다른분이 올린 마이바티스 SQL문 보니 일단 테이블은 TB_TAG,TB_EXHIBIT_TAG 있는데

Group by문에는 왜  TB_TAG 테이블에 관한 필드만 적고 Count()문에는 TB_EXHIBIT_TAG 했는지 헷갈렸다.  

 

해석해보면 일단 Left Join 이니 TB_TAG 데이터 다 가져오는데 예를들어 Group By없다하고  

TB_TAG 에 pk가 1인 데이터 TB_EXHIBIT_TAG에 연관된 데이터가 pk 1,3,6,9 있을시 결과는 이렇게 TB_TAG 데이터 중복으로 나온다. 그래서 GROUP_BY문에 TB_TAG 필드들 적은거고,

Count문은 말그대로 조인했을때 왼쪽 테이블 각 해당 행마다 오른쪽 테이블에 연관된 데이터가 몇개인지 구한거다. 

TB_TAG pk 1데이터 / TB_EXHIBIT_TAG pk 1 데이터,
TB_TAG pk 1데이터 / TB_EXHIBIT_TAG pk 3 데이터,
TB_TAG pk 1데이터 / TB_EXHIBIT_TAG pk 6데이터,
TB_TAG pk 1데이터 / TB_EXHIBIT_TAG pk 9데이터

 

클로드한테 물어보니 위에 쿼리문 결과랑 같으면서 다른 쿼리방식인 서브쿼리 이용한게 있다.

이렇게 TB_EXHIBIT_TAG을 서브쿼리했다.

SELECT
    TAG.IDX,
    TAG.DEPTH_TYPE,
    TAG.DEPTH1_IDX,
    TAG.DEPTH2_IDX,
    TAG.ITEM_ORDER,
    TAG.TAG_NAME_KOR,
    TAG.TAG_NAME_ENG,
    TAG.IS_SHOW,
    COALESCE(ITEM_COUNT.CONNECTED_ITEM_COUNT, 0) AS CONNECTED_ITEM_COUNT,
    TAG.REG_DTTM
FROM
    TB_TAG TAG
LEFT JOIN (
    SELECT 
        TAG_IDX, 
        COUNT(*) AS CONNECTED_ITEM_COUNT
    FROM 
        TB_EXHIBIT_TAG
    GROUP BY 
        TAG_IDX
) ITEM_COUNT ON ITEM_COUNT.TAG_IDX = TAG.IDX
WHERE
    TAG.DEPTH_TYPE != 1
    <if test="depth1_idx != null">
        AND TAG.DEPTH1_IDX = #{depth1_idx}
    </if>
ORDER BY
    TAG.DEPTH1_IDX, TAG.DEPTH2_IDX, TAG.ITEM_ORDER

 

또 다른 방법인 Group by 사용 안하고 중복제거 DISTINCT를 이용하는 방법이 있다

<select id="getTagListWithConnectedItemCount" parameterType="Integer" resultType="TagVo">
    SELECT DISTINCT
        TAG.IDX,
        TAG.DEPTH_TYPE,
        TAG.DEPTH1_IDX,
        TAG.DEPTH2_IDX,
        TAG.ITEM_ORDER,
        TAG.TAG_NAME_KOR,
        TAG.TAG_NAME_ENG,
        TAG.IS_SHOW,
        (SELECT COUNT(EXHIBIT_TAG.IDX) FROM TB_EXHIBIT_TAG EXHIBIT_TAG WHERE EXHIBIT_TAG.TAG_IDX = TAG.IDX) AS CONNECTED_ITEM_COUNT,
        TAG.REG_DTTM
    FROM
        TB_TAG TAG
    WHERE
        TAG.DEPTH_TYPE != 1
        <if test="depth1_idx != null">
            AND TAG.DEPTH1_IDX = #{depth1_idx}
        </if>
    ORDER BY
        TAG.DEPTH1_IDX, TAG.DEPTH2_IDX, TAG.ITEM_ORDER;
</select>

2. GROUP_CONCAT ,  CONCAT() , SEPARATOR

SELECT
    IDX,
    TYPE,
    TITLE_KOR,
    TITLE_ENG,
    START_DATE,
    EXPIRE_DATE,
    REG_DTTM,
    UPD_DTTM,
    LCLASS_TYPE,
    (
        SELECT
            GROUP_CONCAT(CONCAT('#', TAG.TAG_NAME_KOR) ORDER BY TAG.DEPTH1_IDX, TAG.DEPTH2_IDX, TAG.ITEM_ORDER ASC SEPARATOR ' ') AS SELECT_TAG_NAME_KOR
        FROM
            TB_EXHIBIT_TAG EXHIBIT_TAG
            LEFT JOIN TB_TAG TAG ON TAG.IDX = EXHIBIT_TAG.TAG_IDX
        WHERE
            TB_EXHIBIT_CONTENTS.IDX = EXHIBIT_TAG.EXHIBIT_CONTENTS_IDX
        GROUP BY
            EXHIBIT_TAG.EXHIBIT_CONTENTS_IDX
    ) AS SELECT_TAG_NAME_KOR
FROM TB_EXHIBIT_CONTENTS
WHERE  TYPE=#{type}

 

GROUP_CONCAT 함수는 MySQL에서 사용할 수 있는 집계 함수로, 그룹화된 결과를 하나의 문자열로 결합해줍니다. 이 함수는 여러 행의 값을 하나의 문자열로 결합하는 데 유용합니다.

 

CONCAT()는 MySQL의 CONCAT 함수를 사용하여 문자열을 결합하는 부분입니다. 이 함수는 주어진 여러 문자열을 하나의 문자열로 합치는 역할을 합니다.  

TAG.TAG_NAME_KOR이 태그A라면, CONCAT('#', TAG.TAG_NAME_KOR)는 #태그A가 됩니다.

 

SEPARATOR는 MySQL의 GROUP_CONCAT 함수에서 사용되는 옵션으로, 여러 값들을 결합할 때 각각의 값들 사이에 들어갈 구분자를 지정합니다. 기본적으로 GROUP_CONCAT 함수는 쉼표(,)를 사용하여 값들을 구분하지만, SEPARATOR를 사용하여 원하는 구분자를 지정할 수 있습니다.  

(밑에 예시 보면 #태크A   #태크B 이렇게 공백을 넣어주는 역활을 한다) 

 

위에 코드 예시

'플랫폼엘 정리or해석' 카테고리의 다른 글

css,JavaScript관련  (0) 2024.07.18
커스텀 어노테이션 적용후,인터셉터에 적용하기  (0) 2024.07.12
MySql의 암호화,복호화  (0) 2024.07.04
XSS 공격 방지용 XssFilter  (0) 2024.06.25
Json 코드 해석  (0) 2024.06.25