자신감뿅뿅
226
2021-04-12 23:07:57
6
179

mysql 계층형 쿼리..질문드려요.


spring 기반으로 게시판 평가받는중인데


답글부분을 검색했더니 검색한결과로는 update insert 멀티쿼리 써서 하셨길래 따라해서 구현했는데


저렇게하지말고 select 계층형 쿼리써서하고 하길래 


검색해서 계속 보긴했는데 예제가 다똑같고 쿼리에 대한 설명은 없더라구요..(제가못본건지;;)


이때까지 oracle만 쓰다가 처음 mysql 베이스로하는데 쿼리를봐도 이해가안갑니다..


https://shlee0882.tistory.com/241 이 사이트를 기준으로 보고있는데요


혹시나 계층형쿼리 자세하게 설명해준 사이트 추천해주실분있으신가요 ..ㅠ


아니면


SELECT fnc_hierarchi() AS id, @level AS level
        FROM (SELECT @start_with:=0, @id:=@start_with, @level:=0) vars
          JOIN ANIMAL
         WHERE @id IS NOT NULL) fnc


좀 번거로우시겠지만 위 쿼리만이라도 자세하게 설명해주실분 계신가요..
0
  • 답변 6

  • LazyBoy
    132
    2021-04-13 13:58:12 작성 2021-04-13 14:01:51 수정됨

    계층형 쿼리가 뭔지는 잘 모르겠습니다.


    일단 @varname은 세션 변수라 함수 안에서 변하면 그 변한 상태가 유지된 채로 다음 실행에서 다시 쓰이는 것 같습니다. 아래 방식으로 hierarchy구조순대로 id를 재정렬한 테이블을 만들고 그걸 Animals테이블과 조인 시켜서 hierarchy  구조 순번대로 animals를 재정렬 하는 것 같습니다.


    DROP FUNCTION IF EXISTS fnc_hierarchi;
     
    DELIMITER $$
     
    CREATE FUNCTION  fnc_hierarchi() RETURNS INT
     
    NOT DETERMINISTIC
     
    READS SQL DATA
     
    BEGIN
     
        DECLARE v_id INT;
        DECLARE v_parent INT;    
        DECLARE CONTINUE HANDLER FOR NOT FOUND SET @id = NULL;
     
        SET v_parent = @id;
        SET v_id = -1;
     
        IF @id IS NULL THEN
            RETURN NULL;
        END IF;
     
        LOOP
        
        /* 첫번쨰 실행시 v_parent에 @id가 들어 있어 자식 노드가 있나 확인.
          다음 실행 부터는 v_id에 @id가 들어있어 형제노드가 있는지 확인용. */
        SELECT MIN(id)
          INTO @id 
          FROM ANIMAL
         WHERE p_id = v_parent
           AND id > v_id;
     
        /* 현재 Root노드이거나 아직 남은 자식,형제노드가 있으면
           그 노드로 이동해서 id,level 출력 후 다시 함수 호출 */
        IF (@id IS NOT NULL) OR (v_parent = @start_with) THEN
           SET @level = @level + 1;
        RETURN @id;
        END IF;
        

        /* 형제 노드가 없으면 현재 노드의 부모노드로 이동해서 다시 함수 호출 */
        SET @level := @level - 1;
     
        SELECT id, p_id
          INTO v_id , v_parent 
            FROM ANIMAL
           WHERE id = v_parent;
       
        END LOOP;
     
    END
     
    $$
     
    DELIMITER ;
  • 자신감뿅뿅
    226
    2021-04-14 11:49:51

    LazyBoy 님 감사합니다 이해하는데 큰도움이 되었습니다.

  • 자신감뿅뿅
    226
    2021-04-14 15:20:43

    LazyBoy 님 위의 예제를 가지고 게시판에 적용시켰는데 궁금한점이 있어 다시 질문드립니다..


    ELECT fnc_hierarchi() AS bno, @level AS level

            FROM (SELECT @start_with:=0, @bno:=@start_with, @level:=0) vars

              JOIN BOARD;


    이부분을 조회하면


     

    이렇게 제대로 정렬이되는데


    SELECT CASE WHEN LEVEL-1 > 0 then CONCAT(CONCAT(REPEAT('    ', level  - 1),'┗'), brd.title)

                     ELSE brd.title

               END AS title

         , brd.bno

         , brd.p_no

         , fnc.level

      FROM

         (SELECT fnc_hierarchi() AS bno, @level AS level

            FROM (SELECT @start_with:=0, @bno:=@start_with, @level:=0) vars

              JOIN BOARD

             WHERE @bno IS NOT NULL) fnc

      JOIN BOARD brd ON fnc.bno = brd.bno;

    이 쿼리를 조회하면

    위처럼 기존에있던 정렬이 깨지고 그냥 bno 순서대로나옵니다.


    JOIN구문을 고쳐도 결과값이 계속 그대로 나오는데 어느부분이 문제인걸까요?


    그리고 위문제를 해결했을시 게시글이 등록된 오름차순으로 정렬되서 출력되는데


    내림차순으로 게시글을 정렬하려면 어느쪽을 고쳐야되는지 알고싶습니다..

  • LazyBoy
    132
    2021-04-16 20:58:35 작성 2021-04-16 20:59:59 수정됨

    SQL 초보라 저도 잘 모르겠습니다.

    의심가는 것만 말씀드릴게요.

    bno가 hierarcy 순서대로 나온  fnc 테이블을 brd 테이블과 조인해서 새 테이블도 fnc와 똑같은 순서대로 되어야 하는데 맨위 SELECT절에 brd.bno를 쓰셨네요. 저렇게 하면 brd테이블에 나온 순서대로 정렬이 될 것 같습니다. brd.bno가 아니라 fnc.bno나 그냥 bno를 쓰시면 될 것으로 보입니다.

     

    그리고 정렬은 ORDER BY (변수명) DESC로 하면 됩니다.

  • LazyBoy
    132
    2021-04-25 19:54:12

    해결 되신건가요???

  • 자신감뿅뿅
    226
    2021-04-30 12:17:07

    LazyBoy 

    아.. 답변감사합니다 !! 제가 요세 정신이없어서 ;;

    다른방법으로 해결했는데 답변주신부분보니깐

    저렇게 해도 나올꺼같아서 좀있다 테스트한번 해보려고합니다.

    답변주시는거보면 초보보단 잘하시는거같은데 ㅎ,.ㅎ



  • 로그인을 하시면 답변을 등록할 수 있습니다.