{#for-for} # FOR {bdg-primary-line}`GQL 절` {bdg-secondary-line}`2.18에 추가` 리스트를 행으로 펼치며, 요소마다 행 하나를 만들고, 각 요소의 위치를 선택적으로 바인딩합니다. Cypher의 `UNWIND`에 대응하는 GQL 절입니다. {#for-synopsis} ## 개요
FOR variable IN list [ WITH OFFSET [ AS offset_variable ] ]

굵게 키워드 · 기울임 직접 채우는 자리 · [ ] 생략 가능 · ... 반복 가능. 구문 표기 규약을 참고하십시오.

{#for-description} ## 설명 `FOR`는 각 입력 행을 리스트의 요소와 조인하므로, 요소 *n*개인 리스트를 만난 입력 행은 출력 행 *n*개가 됩니다. 리스트가 그 행에 의존한다면 펼치기가 행마다 실행됩니다. - 요소 변수는 **새** 이름이어야 합니다. 유효 범위에 있는 이름을 다시 쓰면 `duplicate variable ""`이 나옵니다. - `WITH OFFSET`은 각 요소의 위치를 바인딩합니다. 그 위치는 **0부터** 셉니다. - 빈 리스트, null인 리스트, 없는 속성은 모두 **행을 하나도** 내놓지 않으므로, 아무것도 없는 것에 대한 `FOR`는 자기 입력 행을 떨어뜨립니다. - 스칼라는 리스트가 아니므로 리스트로 감싸이지 않고 거부됩니다. - `FOR`는 쿼리를 시작하거나, 가운데에 놓이거나, 쓰기 절을 돌릴 수 있습니다. 쿼리를 끝낼 수는 없습니다. {#for-parameters} ## 매개변수 variable : 출력 행마다 요소 하나에 바인딩되는 이름입니다. 이미 유효 범위에 있어서는 안 됩니다. list : 리스트를 내놓는 표현식이면 무엇이든 됩니다. 리터럴, `range()`, 리스트 값을 가진 속성, 앞선 `collect()`가 만든 리스트, `+`로 이어 붙인 두 리스트가 그렇습니다. offset_variable : 요소의 0부터 시작하는 위치에 바인딩되는 이름입니다. `AS` 절을 생략하면 그 위치가 `offset`에 바인딩됩니다. 그것은 예약어이므로 그 뒤로는 어디서나 `"offset"`으로 써야 합니다. `AS` 형태를 쓰는 편이 낫습니다. {#for-examples} ## 예제 모든 예제는 [예제 데이터셋](../../get_started/example-dataset.md)에서 실행됩니다. 제목 리스트를 펼쳐 하나씩 찾아봅니다. `FOR`와 Cypher의 `UNWIND`는 같은 리스트를 펼칩니다. 탭을 바꿔 비교해 보십시오: ::::{tab-set} :::{tab-item} GQL — FOR ```cypher FOR t IN ['The Matrix', 'Inception', 'Gattaca'] MATCH (m:movie {title: t}) RETURN t AS title, m.year AS year ORDER BY year; ``` ::: :::{tab-item} Cypher — UNWIND ```cypher UNWIND ['The Matrix', 'Inception', 'Gattaca'] AS t MATCH (m:movie {title: t}) RETURN t AS title, m.year AS year ORDER BY year; ``` ::: :::: ``` title | year --------------+------ "Gattaca" | 1997 "The Matrix" | 1999 "Inception" | 2010 (3 rows) ``` {#for-number-the-elements-as-they-expand} ### 펼치면서 요소에 번호를 붙이기 `WITH OFFSET AS`가 그 위치에 이름을 붙입니다. 순위가 매겨진 제목 목록처럼 리스트의 순서가 곧 답일 때 필요한 것입니다: ```cypher FOR t IN ['The Matrix', 'Inception', 'Gattaca'] WITH OFFSET AS i MATCH (m:movie {title: t}) RETURN i, t AS title ORDER BY i; ``` ``` i | title ---+-------------- 0 | "The Matrix" 1 | "Inception" 2 | "Gattaca" (3 rows) ``` 첫 요소는 1이 아니라 0에 있습니다. {#for-reach-the-offset-without-naming-it} ### 이름을 붙이지 않고 위치에 손대기 `AS` 절을 빼도 위치는 바인딩되지만, 예약 키워드인 `offset`이라는 이름으로 바인딩됩니다. 그 뒤의 모든 참조는 따옴표로 감싸야 합니다: ```cypher FOR t IN ['The Matrix', 'Inception'] WITH OFFSET RETURN "offset", t; ``` ``` offset | t --------+-------------- 0 | "The Matrix" 1 | "Inception" (2 rows) ``` 따옴표를 빼면 그 쿼리는 파싱되지 않습니다: ```cypher FOR t IN ['The Matrix'] WITH OFFSET RETURN offset, t; ``` ``` ERROR: syntax error at or near "offset" LINE 1: FOR t IN ['The Matrix'] WITH OFFSET RETURN offset, t; ^ ``` {#for-expand-a-list-valued-property} ### 리스트 값을 가진 속성 펼치기 리스트는 일치한 행에서 올 수도 있고, 그 경우 펼치기가 행마다 실행됩니다: ```cypher MATCH (m:movie {title: 'The Matrix'}) FOR e IN m.embedding RETURN e ORDER BY e; ``` ``` e ------------- -0.11921061 -0.07594558 0.04081754 0.29592122 (4 rows) ``` {#for-generate-the-rows-a-query-needs} ### 쿼리가 필요한 행을 만들어 내기 `range()`도 다른 것과 같은 리스트이므로, `FOR`가 생성된 키에 대한 조회를 돌릴 수 있습니다: ```cypher FOR y IN range(1999, 2001) MATCH (m:movie {year: y}) RETURN y, m.title AS film ORDER BY y, film; ``` ``` y | film ------+-------------- 1999 | "The Matrix" (1 row) ``` {#for-notes} ## 참고 `FOR`는 lateral `unnest()`로 컴파일되고, `UNWIND`는 `ProjectSet`으로 컴파일됩니다. 둘은 뜻으로는 바꿔 쓸 수 있지만 같은 실행 계획은 아닙니다: ```cypher EXPLAIN (COSTS OFF) FOR x IN [1, 2, 3] RETURN x; ``` ``` QUERY PLAN -------------------------------------------- Function Scan on unnest _agens_default_for (1 row) ``` 펼치기가 `unnest()`를 지나므로, 스칼라 원천은 요소 하나짜리 리스트가 아니라 타입 오류입니다. 정수는 `function unnest(integer) does not exist`를 내고, 스칼라 속성은 `cannot extract elements from a scalar`를 냅니다. 반대로 null은 빈 리스트로 취급되어 행을 내놓지 않습니다. ```{note} `FOR`는 PostgreSQL에서 이미 예약 키워드이므로, 이 절이 식별자 이름에 새 제한을 더하지는 않습니다. `offset`도 예약어이고, 그래서 `WITH OFFSET`만 쓴 형태는 다시 읽는 자리에서 따옴표로 감싸야 합니다. ``` {#for-compatibility} ## 호환성 ```{admonition} GQL 적합성 :class: gql-conformance GQL *FOR 문장*(ISO/IEC 39075:2024 §14.8), 기능 GQ10 "FOR statement: list value support", 기능 GQ24 "FOR statement: WITH OFFSET"를 구현합니다. - **지원** — 리스트 값 표현식의 전개, 입력 행마다의 평가, null 원본을 빈 리스트로 다루는 것, 그리고 표준이 규정하는 0부터 세는 위치(§14.8 일반 규칙 2의 `j−1`)를 주는 `WITH OFFSET`. - **미지원** — 1부터 세는 짝인 `WITH ORDINALITY`(기능 GQ11). 대신 오프셋에 1을 더하십시오. 원본 자리에 ``을 쓰는 것(기능 GQ23)도 지원하지 않습니다. AgensGraph에는 이름 붙은 바인딩 테이블이 없기 때문입니다. - **이탈** — 표준은 위치 변수를 `AS` 없이 씁니다(`WITH OFFSET i`). AgensGraph는 `WITH OFFSET AS i`를 요구하며, 그냥 쓴 `WITH OFFSET`은 이름을 `offset`으로 정합니다. 진행 상황은 [GQL 적합성 표](../../appendix/gql-conformance.md)에서 확인하십시오. ``` {#for-opencypher} ### openCypher openCypher는 이 절을 [`UNWIND … AS x`](unwind.md)로 표기하며, AgensGraph는 그것을 그대로 받습니다. 그 표기에는 위치를 주는 형태가 없습니다. {#for-see-also} ## 관련 항목 - [`UNWIND`](unwind.md) — 위치가 없는 Cypher의 대응 절 - [`INSERT`](insert.md) {bdg-secondary-line}`GQL` — `FOR`가 돌릴 수 있는 쓰기 - [`LET`](let.md) {bdg-secondary-line}`GQL` - [`FILTER`](filter.md) {bdg-secondary-line}`GQL` — 펼친 행을 좁히기 - [`ORDER BY`](order-by.md) — `FOR`가 내놓은 행을 정렬하기 - [GQL 적합성 표](../../appendix/gql-conformance.md)