SQL 부모 노드 에서 모든 하위 노드 의 실현 방법 찾기
CREATE TABLE category ( id LONG, parentId LONG, name String(20) )
INSERT INTO category VALUES ( 1, NULL, 'Root' )
INSERT INTO category VALUES ( 2, 1, 'Branch1' )
INSERT INTO category VALUES ( 3, 1, 'Branch2' )
INSERT INTO category VALUES ( 4, 3, 'SubBranch1' )
INSERT INTO category VALUES ( 5, 2, 'SubBranch2' )
그 중에서 parent id 는 부모 노드 를 나타 내 고 name 은 노드 이름 입 니 다.현재 특정한 노드 아래 의 모든 하위 노드(후대 Descendants 획득)를 얻 으 려 면 어떻게 해 야 합 니까?프로그램(자바/HP)을 재 귀적 으로 호출 하면 데이터베이스 와 로 컬 개발 언어 사 이 를 오 가 며 효율 이 떨 어 질 것 으로 예상 된다.그래서 우 리 는 데이터 뱅 크 차원 에서 완성 할 수 있 기 를 바 랍 니 다.-어떻게 해 야 합 니까?
귀속 법
조 회 를 통 해 가장 좋 은 방법 은 SQL 재 귀 CTE 의 방법 이 라 고 생각 합 니 다.CTE 란 Common Table Expressison 공용 표 표현 식 이라는 뜻 입 니 다.네티즌 들 은 CTE 는 매우 우아 한 존재 라 고 평가 했다.CTE 가 가 져 온 가장 큰 장점 은 코드 의 가 독성 향상 이다.이것 은 좋 은 코드 의 필수 품질 중 하나 이다."귀속 CTE 를 사용 하면 더욱 가 볍 고 유쾌하게 우아 하고 간결 한 방식 으로 복잡 한 조 회 를 실현 할 수 있다."사실 저 는 SQL 에 익숙 하지 않 습 니 다.여러분,구 글 에서 그 뜻 을 내 려 주시 면 됩 니 다.
CTE 를 어떻게 쓰 지?우 리 는 작은 데이터베이스 SQLite 를 사용 하면 지원 합 니 다!그 는 부피 가 크 지 않 지만 최신 SQL 99 의 with 문 구 를 지원 할 수 있다.예 는 다음 과 같다.
WITH w1( id, parentId, name) AS
( SELECT
category.id,
category.parentId,
category.name
FROM
category
WHERE
id = 1
UNION ALL
SELECT
category.id,
category.parentId,
category.name
FROM
category JOIN w1 ON category.parentId= w1.id
)
SELECT * FROM w1;그 중에서 WHERE id=1 은 그 부모 노드 의 id 입 니 다.변 수 를 바 꿀 수 있 습 니 다.쉽게 말 하면 재 귀 CTE 는 최소 두 개의 조회(구성원 이 라 고도 함)를 포함한다.첫 번 째 조 회 는 지정 한 구성원 이 고 지정 한 구성원 은 유효 표 로 돌아 가 는 조회 일 뿐 재 귀적 인 기초 나 포 지 셔 닝 에 사용 된다.두 번 째 조 회 는 재 귀적 구성원 이 라 고 불 리 며,이 조 회 를 재 귀적 구성원 이 라 고 부 르 는 것 은 CTE 이름 에 대한 재 귀적 인용 이 촉발 되 는 것 입 니 다.논리 적 으로 CTE 이름 의 내부 응용 을 이전 조회 의 결과 집합 으로 이해 할 수 있다.재 귀 조 회 는 명시 적 인 재 귀 종료 조건 이 없 으 며,두 번 째 재 귀 조회 가 빈 결과 집합 으로 돌아 가 거나 재 귀 횟수 의 최대 제한 을 초과 할 때 만 재 귀 를 중단 합 니 다.재 귀 횟수 상한 선 을 두 는 방법 은 맥 스 리 큐 리 온 을 사용 하 는 것 이다.이에 따라 모든 부모 노드 를 찾 는 방법 을 제시 합 니 다.(조상 Ancestors 를 얻 는 것 은 id 와 parentId 를 거꾸로 하 는 것 입 니 다)
WITH w1( id, parentId, name, level) AS
( SELECT
id,
parentId,
name,
0 AS level
FROM
category
WHERE
id = 6
UNION ALL
SELECT
category.id,
category.parentId,
category.name ,
level + 1
FROM
category JOIN w1 ON category.id= w1.parentId
)
SELECT * FROM w1;
어 쩔 수 없 는 MySQLSQLite ok 인 데 MySQL 은 요?
다른 쪽 에 서 는 모두 가 즐겨 쓰 는 MySQL 이 with 문 구 를 무시 하고 홈 페이지 블 로그 에 서 는 전혀 지원 하지 않 고 불편 하 다 는 것 을 명확 하 게 설명 하고 있 습 니 다.간단 한 일 을 할 수 있 는데 왜 사용 하지 못 합 니까?그리고 MySQL 도 미래의 새 버 전에 with 의 cte 기능 을 추가 할 계획 이 없 는 것 같 습 니 다.그래서 모두 많은 방법 을 생각해 냈 다.사실은 재 귀 프로그램 이 잖 아 요.어렵 지 않 을 거 예요.함수 나 저장 과정 을 써 야 되 는 거 죠?맞 아,맞 아.-재 귀 는 문제 가 아니 야.문 제 는 SQL 로 쓰 는 게 문제 야.아니면 그 말 이 야?'줄 을 사이 에 두 고 산 을 사이 에 두 고'라 는 말 이 야.과장 되 는 말 이지 만 데이터 베 이 스 를 알 면서 도 각종 데이터 베이스 방언 쓰기(저장 과정)를 아 는 사람 은 많 지 않 을 거 야.-잘 따 지지 않 아.어차피 코드 가 붙 어 다 니 는 거 잖 아.
SQL 을 붙 이지 않 겠 습 니 다.여 기 를 볼 수 있 습 니 다.
이로써 우리 의 목적 은 이미 달성 되 었 고 괜찮다 고 할 수 있다.왜냐하면 이것 은 층수 에 제한 이 없 기 때문이다.사실은 일반적인 상황 에서 층수 가 3 층 을 넘 으 면 매우 많 고 복잡 하 다.일반 사용자 들 은 특별한 수요 가 없 으 면 이렇게 많은 층 을 사용 할 수 없다.그래서 주어진 층수 의 제약 하에 서 표준 SQL 을 써 서 이 임 무 를 완성 할 수 있 습 니 다.약간 죽은 느낌 이지 만~
SELECT t1.name AS lev1, t2.name as lev2, t3.name as lev3, t4.name as lev4
FROM category AS t1
LEFT JOIN category AS t2 ON t2.parentId = t1.id
LEFT JOIN category AS t3 ON t3.parentId = t2.id
LEFT JOIN category AS t4 ON t4.parentId = t3.id
WHERE t1.id= 1
이에 따라 모든 부모 노드 를 찾 는 방법 을 제시 합 니 다.(조상 Ancestors 를 얻 는 것 은 id 와 parentId 를 거꾸로 하 는 것 입 니 다)
SELECT t1.name AS lev1, t2.name as lev2, t3.name as lev3, t4.name as lev4
FROM category AS t1
LEFT JOIN category AS t2 ON t2.id= t1.parentId
LEFT JOIN category AS t3 ON t3.id= t2.parentId
LEFT JOIN category AS t4 ON t4.id= t3.parentId
WHERE t1.id=10 최적화 버 전
그러나 생 성 된 결 과 는 첫 번 째 예 에 비해 좀 이상 하고 자바 에 게 사용 하기 가 쉽 지 않다.그럼 다른 예 를 찾 아 보 자.
SELECT
p1.id,
p1.name,
p1.parentId as parentId,
p2.parentId as parent2_id,
p3.parentId as parent3_id,
p4.parentId as parent4_id,
p5.parentId as parent5_id,
p6.parentId as parent6_id
FROM category p1
LEFT JOIN category p2 on p2.id = p1.parentId
LEFT JOIN category p3 on p3.id = p2.parentId
LEFT JOIN category p4 on p4.id = p3.parentId
LEFT JOIN category p5 on p5.id = p4.parentId
LEFT JOIN category p6 on p6.id = p5.parentId
WHERE 1 IN (p1.parentId,
p2.parentId,
p3.parentId,
p4.parentId,
p5.parentId,
p6.parentId)
ORDER BY 1, 2, 3, 4, 5, 6, 7; 이것 은 마침내 모양 이 좀 비슷 해 졌 는데,결 과 는 이렇게 되 었 다.
이에 따라 모든 부모 노드 를 찾 는 방법 을 알려 줍 니 다.(조상 Ancestors 를 얻 는 것 은 id 와 parentId 를 반대로 하고 IN 의 필드 이름 을 바 꾸 는 것 입 니 다)
SELECT
p1.id,
p1.name,
p1.parentId as parentId,
p2.parentId as parent2_id,
p3.parentId as parent3_id
FROM category p1
LEFT JOIN category p2 on p2.parentId = p1.id
LEFT JOIN category p3 on p3.parentId = p2.id
WHERE 9 IN (p1.id,
p2.id,
p3.id)
ORDER BY 1, 2, 3;
이렇게 하면 통용 된다~SQLite 든 MySQL 이 든.기타 조회:
직접 하위 노드 의 총 수 를 조회 합 니 다:
SELECT c.*
, (SELECT COUNT(*) FROM category c2 WHERE c2.parentId = c.id)
AS direct_children
FROM category c
•with 문 구 를 사용 하여 재 귀적 이 고 알 기 쉬 운 예(영어)를 사용 합 니 다.제 첫 번 째 성공 적 인 예 는 바로 여기 서 copy 한 것 입 니 다.또한 층수 level 과 역방향 의 부모 노드 도 찾 을 수 있 습 니 다.https://www.valentina-db.com/dokuwiki/doku.php?id=valentina:articles:recursive_query•표준 서법 의 출처(영어):http://stackoverflow.com/questions/20215744/how-to-create-a-mysql-hierarchical-recursive-query
•좋 은 요약 스티커(영어):http://mikehillyer.com/articles/managing-hierarchical-data-in-mysql/
•SQLite with 구문 용법 중국어 번역(너무 어려워 새 를 몰라)http://blog.csdn.net/aflyeaglenku/article/details/50978986
•폐쇄 적 으로 만 든 나무 구조(책 에 서 는 이 방법 이 가장 좋다 고 하지만 동시에 고 급 스 럽 다 고 생각 합 니 다.영어)http://charlesleifer.com/blog/querying-tree-structures-in-sqlite-using-python-and-the-transitive-closure-extension/
이상 의 SQL 부모 노드 에서 모든 하위 노드 를 찾 는 실현 방법 은 바로 편집장 이 여러분 에 게 공유 한 모든 내용 입 니 다.여러분 에 게 참고 가 되 고 여러분 들 이 저 희 를 많이 사랑 해 주 셨 으 면 좋 겠 습 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Redash를 사용할 때 몰랐던 SQL을 쓰는 법을 배웠습니다.최근 redash에서 sql을 쓸 기회가 많고, 이런 쓰는 방법이 있었는지와 sql에 대해 공부를 다시하고 있기 때문에 배운 것을 여기에 씁니다. Redash란? 월별로 데이터를 표시하고 싶습니다 주별로 데이터를 표...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.