MySQL에서 재귀 SELECT 쿼리를 수행하는 방법
다음 테이블이 있습니다.
col1 | col2 | col3
-----+------+-------
1 | a | 5
5 | d | 3
3 | k | 7
6 | o | 2
2 | 0 | 8
가 "은 "1"을 .col1
"가진 "1"의 .col3
라고 하면 은 '5'에서를 계속 합니다.col1
'3'에서 '이 나옵니다.col3
출력할 수중에 있습니다.
1 | a | 5
5 | d | 3
3 | k | 7
유저가 「6」을 검색하면, 다음의 출력이 됩니다.
6 | o | 2
2 | 0 | 8
★★★★의 방법SELECT
문할할 수???
편집
@leftclickben에서 언급한 솔루션도 효과적입니다.스토어드 프로시저를 동일하게 사용할 수도 있습니다.
CREATE PROCEDURE get_tree(IN id int)
BEGIN
DECLARE child_id int;
DECLARE prev_id int;
SET prev_id = id;
SET child_id=0;
SELECT col3 into child_id
FROM table1 WHERE col1=id ;
create TEMPORARY table IF NOT EXISTS temp_table as (select * from table1 where 1=0);
truncate table temp_table;
WHILE child_id <> 0 DO
insert into temp_table select * from table1 WHERE col1=prev_id;
SET prev_id = child_id;
SET child_id=0;
SELECT col3 into child_id
FROM TABLE1 WHERE col1=prev_id;
END WHILE;
select * from temp_table;
END //
출력 결과를 저장하기 위해 임시 테이블을 사용하고 있으며 임시 테이블은 세션 기반이기 때문에 출력 데이터가 잘못되어도 문제가 없습니다.
SQL FIDDLE Demo
다음 쿼리를 사용해 보십시오.
SELECT
col1, col2, @pv := col3 as 'col3'
FROM
table1
JOIN
(SELECT @pv := 1) tmp
WHERE
col1 = @pv
다음과 같습니다SQL FIDDLE Demo
.
| COL1 | COL2 | COL3 |
+------+------+------+
| 1 | a | 5 |
| 5 | d | 3 |
| 3 | k | 7 |
★★★
parent_id
값은 이보다 .child_id
이 솔루션이 작동하도록 합니다.
@Meherzad에 의해 받아들여진 답변은 데이터가 특정 순서로 되어 있는 경우에만 기능합니다.OP 질문의 데이터로 동작합니다.제 경우 데이터를 사용하기 위해 수정해야 했습니다.
주 이것은 모든 레코드의 "id"(질문의 col1)가 해당 레코드의 "parent id"(질문의 col3)보다 큰 값을 가질 때만 작동합니다.일반적으로 가장 먼저 부모를 생성해야 하기 때문에 이러한 경우가 많습니다.그러나 프로그램이 항목을 다른 위치에서 다시 상위 항목으로 지정할 수 있는 계층에 대한 변경을 허용하는 경우, 이를 신뢰할 수 없습니다.
이것은 누군가에게 도움이 되는 경우에 대비한 질문입니다.데이터가 위에서 설명한 필수 구조를 따르지 않기 때문에 주어진 질문에서는 작동하지 않습니다.
select t.col1, t.col2, @pv := t.col3 col3
from (select * from table1 order by col1 desc) t
join (select @pv := 1) tmp
where t.col1 = @pv
점은 '하다'는 것입니다.table1
하고 있습니다.col1
위해서의 「부모」는 「부모」의 「col1
을 이용하다)
좌클릭벤의 답변은 효과가 있었지만, 저는 주어진 노드에서 루트로 돌아가는 경로를 원했습니다.이것들은 반대 방향으로 가고 있는 것 같았습니다. 트리 아래로요.그래서 몇 개의 필드를 뒤집고 이름을 바꿨어요. 그리고 이건 저에게도 효과가 있어요. 만약 다른 사람들도 이걸 원할지도 모르니까요.
item | parent
-------------
1 | null
2 | 1
3 | 1
4 | 2
5 | 4
6 | 3
그리고.
select t.item_id as item, @pv:=t.parent as parent
from (select * from item_tree order by item_id desc) t
join
(select @pv:=6)tmp
where t.item_id=@pv;
다음과 같은 기능이 있습니다.
item | parent
-------------
6 | 3
3 | 1
1 | null
저장 프로시저가 가장 좋은 방법입니다.왜냐하면 메헤르자드의 솔루션은 데이터가 동일한 순서를 따를 경우에만 작동하기 때문입니다.
이런 테이블 구조를 가지고 있다면
col1 | col2 | col3
-----+------+------
3 | k | 7
5 | d | 3
1 | a | 5
6 | o | 2
2 | 0 | 8
효과가 없을 것이다.SQL Fiddle Demo
다음은 동일한 작업을 수행하기 위한 샘플 절차 코드입니다.
delimiter //
CREATE PROCEDURE chainReaction
(
in inputNo int
)
BEGIN
declare final_id int default NULL;
SELECT col3
INTO final_id
FROM table1
WHERE col1 = inputNo;
IF( final_id is not null) THEN
INSERT INTO results(SELECT col1, col2, col3 FROM table1 WHERE col1 = inputNo);
CALL chainReaction(final_id);
end if;
END//
delimiter ;
call chainReaction(1);
SELECT * FROM results;
DROP TABLE if exists results;
부모 ID가 자녀 ID보다 낮아야 하는 문제 없이 SELECT를 사용할 수 있도록 하려면 함수를 사용할 수 있습니다.또, 복수의 아이(트리가 필요한 경우)를 서포트해, 트리는 복수의 헤드를 가질 수 있습니다.또한 데이터에 루프가 존재하는 경우에도 중단됩니다.
테이블/컬럼 이름을 전달하기 위해 동적 SQL을 사용하고 싶었지만 MySQL의 함수는 이를 지원하지 않습니다.
DELIMITER $$
CREATE FUNCTION `isSubElement`(pParentId INT, pId INT) RETURNS int(11)
DETERMINISTIC
READS SQL DATA
BEGIN
DECLARE isChild,curId,curParent,lastParent int;
SET isChild = 0;
SET curId = pId;
SET curParent = -1;
SET lastParent = -2;
WHILE lastParent <> curParent AND curParent <> 0 AND curId <> -1 AND curParent <> pId AND isChild = 0 DO
SET lastParent = curParent;
SELECT ParentId from `test` where id=curId limit 1 into curParent;
IF curParent = pParentId THEN
SET isChild = 1;
END IF;
SET curId = curParent;
END WHILE;
RETURN isChild;
END$$
기기 、 이 here 。test
이치노ParentId,Id를 사용하다
사용방법:
SET @wantedSubTreeId = 3;
SELECT * FROM test WHERE isSubElement(@wantedSubTreeId,id) = 1 OR ID = @wantedSubTreeId;
결과:
3 7 k
5 3 d
9 3 f
1 5 a
테스트 작성용 SQL:
CREATE TABLE IF NOT EXISTS `test` (
`Id` int(11) NOT NULL,
`ParentId` int(11) DEFAULT NULL,
`Name` varchar(300) NOT NULL,
PRIMARY KEY (`Id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
insert into test (id, parentid, name) values(3,7,'k');
insert into test (id, parentid, name) values(5,3,'d');
insert into test (id, parentid, name) values(9,3,'f');
insert into test (id, parentid, name) values(1,5,'a');
insert into test (id, parentid, name) values(6,2,'o');
insert into test (id, parentid, name) values(2,8,'c');
편집: 여기 직접 테스트할 수 있는 바이올린이 있습니다.미리 정의된 딜리미터를 사용하여 딜리미터를 변경할 수 밖에 없었습니다만, 정상적으로 동작합니다.
마스터 DJon을 기반으로 구축
다음은 깊이 반환의 추가 유틸리티를 제공하는 단순화된 함수입니다(특정 깊이에서 상위 작업 또는 검색을 포함하기 위해 논리를 사용하는 경우).
DELIMITER $$
FUNCTION `childDepth`(pParentId INT, pId INT) RETURNS int(11)
READS SQL DATA
DETERMINISTIC
BEGIN
DECLARE depth,curId int;
SET depth = 0;
SET curId = pId;
WHILE curId IS not null AND curId <> pParentId DO
SELECT ParentId from test where id=curId limit 1 into curId;
SET depth = depth + 1;
END WHILE;
IF curId IS NULL THEN
set depth = -1;
END IF;
RETURN depth;
END$$
사용방법:
select * from test where childDepth(1, id) <> -1;
언급URL : https://stackoverflow.com/questions/16513418/how-to-do-the-recursive-select-query-in-mysql
'source' 카테고리의 다른 글
MariaDB는 여러 서브쿼리가 있는 여러 행에 "삽입" (0) | 2022.09.05 |
---|---|
#1273 - 불분명한 대조: 'utf8mb4_unicode_ci' cPanel (0) | 2022.09.05 |
MySQL과 Maria의 패스워드 해시 차이점DB (0) | 2022.09.05 |
MySQL, 두 열 연결 (0) | 2022.09.05 |
PHP 7 이전 "문자열 인스턴스여야 합니다, 문자열 given"을 해결하려면 어떻게 해야 합니까? (0) | 2022.09.05 |