[SQL] 어떻게 재귀 CTE는 라인으로 줄을 실행 하는가?
SQL어떻게 재귀 CTE는 라인으로 줄을 실행 하는가?
나는 쓰기 하나에 이르기까지 충분히 재귀 CTE를의 형식을 가지고 생각하지만, 여전히 나 자신은 내가 수동으로 일합니다 (SQL 엔진을 자신하고 펜과 종이로 결과 집합에 도달 척) 처리 할 수 있다는 것은 마지막에 좌절 찾기 . 나는 가까운 내가 무엇을 찾고에있는이를 찾았지만 충분히 설명하지했습니다. 나는 더는 C를 통해 추적 문제 ++ 순환 기능과 실행 방법을 이해가 없다 -하지만 SQL 내가 왜 또는 엔진이 정지 아는 방법을 이해하지 않습니다. 앵커 및 재귀 블록마다 호출되는, 또는 앵커 나중에 반복으로 건너 뜁니다합니까? (나는 그것을 의심하지만 난 그게 움직이지 것으로 보인다 방식에 대한 표현에 내 혼란을 시도하고있다.) 앵커가 때마다 호출되는 경우, 어떻게 최종 결과에서 여러 번 앵커 표시되지 않습니다? 나는 누군가가 단지 1 호선 2 호선 등 어떤 일이 어떤 결과 세트 늘어남에 따라 "메모리"입니다 다운 휴식을 할 수 있기를 바랍니다.
이해하기 쉬운 것으로 보인다 이후,이 페이지에서 내 예를 훔쳐의 자유를 촬영했습니다.
DECLARE @tbl TABLE (
Id INT
, [Name] VARCHAR(20)
, ParentId INT
)
INSERT INTO @tbl( Id, Name, ParentId )
VALUES
(1, 'Europe', NULL)
,(2, 'Asia', NULL)
,(3, 'Germany', 1)
,(4, 'UK', 1)
,(5, 'China', 2)
,(6, 'India', 2)
,(7, 'Scotland', 4)
,(8, 'Edinburgh', 7)
,(9, 'Leith', 8)
;
WITH abcd
AS (
-- anchor
SELECT id, Name, ParentID,
CAST(Name AS VARCHAR(1000)) AS Path
FROM @tbl
WHERE ParentId IS NULL
UNION ALL
--recursive member
SELECT t.id, t.Name, t.ParentID,
CAST((a.path + '/' + t.Name) AS VARCHAR(1000)) AS "Path"
FROM @tbl AS t
JOIN abcd AS a
ON t.ParentId = a.id
)
SELECT * FROM abcd
해결법
-
==============================
1.끝없는 UNION ALL의 같은 재귀 CTE의 생각 :
끝없는 UNION ALL의 같은 재귀 CTE의 생각 :
WITH rows AS ( SELECT * FROM mytable WHERE anchor_condition ), rows2 AS ( SELECT * FROM set_operation(mytable, rows) ), rows3 AS ( SELECT * FROM set_operation(mytable, rows2) ), … SELECT * FROM rows UNION ALL SELECT * FROM rows2 UNION ALL SELECT * FROM rows3 UNION ALL …
귀하의 경우에는, 그 것이다 :
WITH abcd1 AS ( SELECT * FROM @tbl t WHERE ParentId IS NULL ), abcd2 AS ( SELECT t.* FROM abcd1 JOIN @tbl t ON t.ParentID = abcd1.id ), abcd3 AS ( SELECT t.* FROM abcd2 JOIN @tbl t ON t.ParentID = abcd2.id ), abcd4 AS ( SELECT t.* FROM abcd3 JOIN @tbl t ON t.ParentID = abcd3.id ), abcd5 AS ( SELECT t.* FROM abcd4 JOIN @tbl t ON t.ParentID = abcd4.id ), abcd6 AS ( SELECT t.* FROM abcd5 JOIN @tbl t ON t.ParentID = abcd5.id ) SELECT * FROM abcd1 UNION ALL SELECT * FROM abcd2 UNION ALL SELECT * FROM abcd3 UNION ALL SELECT * FROM abcd4 UNION ALL SELECT * FROM abcd5 UNION ALL SELECT * FROM abcd6
abcd6 수익률 결과가 없습니다 때문에, 이것은 정지 상태를 의미한다.
이론적으로, 재귀 CTE가 무한이 될 수 있지만, 실제적으로, SQL Server는 무한 레코드로 이어질 것 쿼리를 금지하려고합니다.
이 문서를 읽을 수 있습니다 :
-
==============================
2.CTE 사용인지 알고리즘 :
CTE 사용인지 알고리즘 :
예를 취할 수 있습니다 :
WITH cte ( value ) AS ( SELECT 1 UNION ALL SELECT value + 1 FROM cte WHERE value < 4 ) SELECT * FROM cte
이 쿼리의 결과는 다음과 같습니다
value ----------- 1 2 3 4 (4 row(s) affected)
의 단계에 의해 단계를 살펴 보자 :
Execute anchor query (SELECT 1), we got: r0 = 1 cte = r0 = 1 | | V Now we execute SELECT value + 1 FROM cte WHERE value < 4 Since cte is r0 (only has 1), we got: r1 = 2 cte = r1 = 2 | | V Now we execute SELECT value + 1 FROM cte WHERE value < 4 Since cte is r1 (only has 2), we got: r2 = 3 cte = r2 = 3 | | V Now we execute SELECT value + 1 FROM cte WHERE value < 4 Since cte is r2 (only has 3), we got: r3 = 4 cte = r3 = 4 | | V Now we execute SELECT value + 1 FROM cte WHERE value < 4 Since cte is r3 (only has 4), we got: r4 = NULL (because r3 (4) is equal to 4, not less than 4) Now we stop the recursion! | | V Let's calculate the final result: R = r0 union all r1 union all r2 union all r3 union all = 1 union all 2 union all 3 union all 4 union all = 1 2 3 4
-
==============================
3.나는 다음과 같은 고장 생각 :
나는 다음과 같은 고장 생각 :
이 페이지는 아마 가장 잘 설명합니다. 그것은 CTE의 실행 경로 단계별 연습을 갖는다.
-
==============================
4.당신은 아마이 링크를하고자했다. 아니, 앵커가 실행되지 않고 여러 번 (그 다음 노동 조합 모두가 모든 결과에 나타난 요구, 수 없습니다). 이전 링크에서 세부 사항.
당신은 아마이 링크를하고자했다. 아니, 앵커가 실행되지 않고 여러 번 (그 다음 노동 조합 모두가 모든 결과에 나타난 요구, 수 없습니다). 이전 링크에서 세부 사항.
-
==============================
5.1 단계:
1 단계:
1 Europe NULL Europe 2 Asia NULL Asia
2 단계:
1 Europe NULL Europe 2 Asia NULL Asia 3 Germany 1 Europe/Germany 4 UK 1 Europe/UK 5 China 2 Asia/China 6 India 2 Asia/India
3 단계 :
1 Europe NULL Europe 2 Asia NULL Asia 3 Germany 1 Europe/Germany 4 UK 1 Europe/UK 5 China 2 Asia/China 6 India 2 Asia/India 7 Scotland 4 Europe/UK/Scotland
4 단계 :
1 Europe NULL Europe 2 Asia NULL Asia 3 Germany 1 Europe/Germany 4 UK 1 Europe/UK 5 China 2 Asia/China 6 India 2 Asia/India 7 Scotland 4 Europe/UK/Scotland 8 Edinburgh 7 Europe/UK/Scotland/Edinburgh
5 단계 :
1 Europe NULL Europe 0 2 Asia NULL Asia 0 3 Germany 1 Europe/Germany 1 4 UK 1 Europe/UK 1 5 China 2 Asia/China 1 6 India 2 Asia/India 1 7 Scotland 4 Europe/UK/Scotland 2 8 Edinburgh 7 Europe/UK/Scotland/Edinburgh 3 9 Leith 8 Europe/UK/Scotland/Edinburgh/Leith 4
5 단계에서 마지막 열은 수준이다. 각 단계 동안 행은 이미 무엇인지에 대한 추가됩니다. 도움이 되었기를 바랍니다.
from https://stackoverflow.com/questions/3187850/how-does-a-recursive-cte-run-line-by-line by cc-by-sa and MIT license
'SQL' 카테고리의 다른 글
[SQL] 어떤 SQL 쿼리, 더 나은 MATCH 반대 또는 LIKE입니까? (0) | 2020.04.18 |
---|---|
[SQL] 어떻게 데이터베이스의 동시 업데이트를 처리하는? (0) | 2020.04.18 |
[SQL] 나는 SQL 표 JSON 또는 XML 데이터를 저장할 수있는 경우 (0) | 2020.04.18 |
[SQL] SQL 서버 운영 체제 오류 5 : "5 (액세스가 거부되었습니다.)" (0) | 2020.04.18 |
[SQL] JSON 함수에 SQL 서버 SELECT (0) | 2020.04.18 |