MySQL 계층적 재귀 쿼리를 어떻게 생성하나요?
P粉329425839
2023-08-23 21:55:29
<p>저는 MySQL 表,如下所示:</p>
<테이블 클래스="s-테이블">
<머리>
<tr>
<th style="text-align:center;">id</th>
<th style="text-align:center;">이름</th>
<th style="text-align:center;">parent_id</th>
</tr>
</머리>
<본문>
<tr>
<td style="text-align:center;">19</td>
<td style="text-align:center;">类别1</td>
<td style="text-align:center;">0</td>
</tr>
<tr>
<td style="text-align:center;">20</td>
<td style="text-align:center;">类别2</td>
<td style="text-align:center;">19</td>
</tr>
<tr>
<td style="text-align:center;">21</td>
<td style="text-align:center;">类别3</td>
<td style="text-align:center;">20</td>
</tr>
<tr>
<td style="text-align:center;">22</td>
<td style="text-align:center;">类别4</td>
<td style="text-align:center;">21</td>
</tr>
<tr>
<td style="text-align:center;">...</td>
<td style="text-align:center;">...</td>
<td style="text-align:center;">...</td>
</tr>
</tbody>
</테이블>
<p>现재,我想要一个 MySQL 查询,我只需向其提供 id [例如 <code>id=19</code>],然后我应该获取其所有子 id [即结果应id가 '있습니다. 20,21,22']....</p>
<p>子级的层次结构未知;它可能会有所不同......</p>
<p>我知道如何使用 <code>for</code> 循环来做到这一点...但是如何使用单个 MySQL은 查询来实现와 유사합니까?</p>
MySQL 8+의 경우: 재귀적
使用
구문을 사용하세요.MySQL 5.x의 경우: 인라인 변수, 경로 ID 또는 자체 조인을 사용합니다.
MySQL 8+
으아아아parent_id = 19
中指定的值应设置为您要选择其所有后代的父级的id
.MySQL 5.x
공용 테이블 표현식을 지원하지 않는 MySQL 버전(최대 버전 5.7)의 경우 다음 쿼리를 사용하여 이를 달성할 수 있습니다.
으아아아이것은 바이올린입니다.
여기,
@pv := '19'
中指定的值应设置为您要选择其所有后代的父级的id
. p>이 방법은 부모에게 자녀가 여러 명 있는 경우에도 적용됩니다. 그러나 각 레코드는
parent_id 조건을 충족해야 하며, 그렇지 않으면 결과가 불완전합니다.
쿼리 내 변수 할당
이 쿼리는 특정 MySQL 구문을 사용합니다. 즉, 실행 중에 변수가 할당되고 수정됩니다. 실행 순서에 대해 몇 가지 가정을 했습니다.
from
子句。这就是@pv
가 초기화되는 위치를 먼저 평가합니다.from
别名检索的顺序对每条记录评估where
子句。因此,这里设置的条件仅包括父级已被识别为位于后代树中的记录(主要父级的所有后代都将逐步添加到@pv
에서 팔로우하세요).where
子句中的条件按顺序求值,一旦总结果确定,求值就会中断。因此,第二个条件必须位于第二位,因为它将 id 添加到父列表中,并且只有在 id 通过第一个条件时才会发生这种情况。调用length
函数只是为了确保此条件始终为真,即使pv
문자열은 어떤 이유로든 잘못된 값을 생성합니다.대체로 이러한 가정은 너무 위험해서 의존할 수 없습니다. 문서경고:
따라서 위의 쿼리와 일치하더라도 평가 순서는 여전히 변경될 수 있습니다. 예를 들어 조건을 추가하거나 이 쿼리를 더 큰 쿼리 내의 뷰 또는 하위 쿼리로 사용하는 경우입니다. 이는 향후 MySQL 버전 에서 제거될 "기능" 一>입니다:
위에서 언급했듯이 MySQL 8.0부터는 재귀적
with
구문을 사용해야 합니다.효율성
매우 큰 데이터 세트의 경우
find_in_set
작업이 목록에서 숫자를 찾는 가장 이상적인 방법이 아니며 반환된 레코드 수와 일치하는 경우에도 확실히 아니기 때문에 이 솔루션은 느릴 수 있습니다.대안 1:
使用递归
,连接
점점 더 많은 데이터베이스가 SQL:1999 ISO 표준
WITH [RECURSIVE]递归查询的
구문 을 구현합니다(예: Postgres 8.4+ , SQL Server 2005+ a>, DB2, Oracle 11gR2+, SQLite 3.8.4+ , 파이어버드 2.1 +, H2, HyperSQL 2.1.0+, Teradata, MariaDB 10.2.2+). 버전 8.0부터 MySQL도 이를 지원합니다. 사용할 구문은 이 답변의 상단을 참조하세요.일부 데이터베이스에는 Oracle, DB2, Informix과 같은 계층적 조회를 위한 대체 비표준 구문이 있습니다. CUBRID a> 및 기타 데이터베이스
.MySQL 버전 5.7은 이러한 기능을 제공하지 않습니다. 데이터베이스 엔진이 이 구문을 제공하거나 이 구문을 제공하는 데이터베이스 엔진으로 마이그레이션할 수 있는 경우 이는 의심할 여지 없이 최선의 선택입니다. 그렇지 않은 경우 다음 대안을 고려하십시오.
대안 2: 경로 스타일 식별자
계층적 정보(경로)가 포함된 id 값을 지정하면 작업이 훨씬 쉬워집니다. 예를 들어, 귀하의 경우 다음과 같을 수 있습니다:
그러면
으아악选择
가 다음과 같이 보일 것입니다:대안 3: 자체 조인 반복
계층 트리 깊이의 상한을 알고 있는 경우 다음과 같은 표준
으아악sql
쿼리를 사용할 수 있습니다.이것을 보세요 바이올린
where
조건은 검색하려는 부모의 자손을 지정합니다. 필요에 따라 이 쿼리를 더 많은 수준으로 확장할 수 있습니다.