굵게 키워드 · 기울임 직접 채우는 자리 · [ ] 생략 가능 · ... 반복 가능. 구문 표기 규약을 참고하십시오.
{#with-description}
## 설명
`WITH`는 파이프라인의 한 구역을 닫고 다음 구역을 엽니다. [`RETURN`](return.md)과 정확히 같은
방식으로 행마다 표현식을 평가하고, 그 결과 컬럼을 뒤따르는 절에 넘깁니다. 세 가지 일에 이것이
필요합니다:
- **집계한 다음 걸러 내거나 더 일치시키기.** 집계 함수는 `WHERE`에 올 수 없으므로, `WITH`에서
집계하고 그 출력을 걸러 내십시오.
- **값을 한 번만 계산해** 뒤따르는 여러 절에서 쓰기.
- 쿼리의 비싼 부분이 실행되기 전에 `DISTINCT`·`ORDER BY`·`LIMIT`으로 **파이프라인을 줄이기.**
이것이 투영이라는 점에서 따라오는 규칙들입니다:
- `WITH`는 유효 범위를 **교체합니다.** 투영한 것만 살아남습니다. 빼놓은 변수는 사라지고, 그것을
뒤에서 언급하면 `variable does not exist`가 나옵니다. 버리지 않고 더하려면
`WITH *, expr AS v`로 쓰거나 [`LET`](let.md)을 쓰십시오.
- 각 출력 이름은 **그 절 안에서 고유**해야 합니다. 같은 이름을 두 번 투영하면
`WITH passes on "..." more than once`가 나옵니다. `RETURN`에는 그런 규칙이 없습니다.
- 이 절의 `WHERE`는 투영과 집계가 끝난 **뒤에** 실행되므로, 집계의 별칭을 검사할 수 있습니다.
- `ORDER BY`, `SKIP`/`OFFSET`, `LIMIT`은 `WITH` 뒤에 오는 별개의 절이고, 따라서 그 `WHERE`
뒤에도 옵니다. 필터가 먼저 실행되고, 페이지 나누기는 살아남은 것에 적용됩니다.
- `WITH`는 쿼리를 **시작**할 수도, 끝낼 수도 없습니다. 문장 맨 앞의 `WITH`는 SQL의 공통 테이블
표현식이고, 그것은 이름과 괄호로 감싼 쿼리를 받는 다른 절입니다. [`LET`](let.md)에는 그런 충돌이
없어서 쿼리를 시작할 수 있습니다.
{#with-parameters}
## 매개변수
DISTINCT
: 투영한 행을 넘기기 전에 중복 행을 없앱니다.
ALL
: 중복 행을 그대로 둡니다. 기본값입니다.
\*
: 유효 범위의 이름 있는 모든 바인딩을 그대로 통과시킵니다. `WITH *, expr AS v`처럼 다른 항목과 함께
쓰면 어떤 컬럼도 버리지 않고 컬럼을 더할 수 있습니다.
expression
: 유효 범위의 바인딩에 대한 Cypher 표현식이면 무엇이든 되고, 집계 함수도 됩니다.
alias
: 다음 절이 쓰는 이름입니다. 변수 참조만 있는 것이 아니라면 필수입니다. 뒤따르는 절이 그것을
이름으로 부를 수 있어야 하기 때문입니다.
condition
: 투영된 행을 걸러 내는 불리언 표현식입니다. 투영 뒤에 평가되므로 이 절에서 정의한 별칭을 가리킬 수
있습니다.
{#with-examples}
## 예제
모든 예제는 [예제 데이터셋](../../get_started/example-dataset.md)에서 실행됩니다.
{#with-filter-on-a-count}
### 개수로 걸러 내기
```cypher
MATCH (p:person)-[:acted_in]->(m:movie)
WITH p.name AS actor, count(m) AS films
WHERE films > 1
RETURN actor, films
ORDER BY films DESC, actor;
```
```
actor | films
-------------------------+-------
"Keanu Reeves" | 4
"Arnold Schwarzenegger" | 3
"Carrie-Anne Moss" | 2
"Harrison Ford" | 2
"Laurence Fishburne" | 2
"Linda Hamilton" | 2
(6 rows)
```
`count(m)`이 `p.name`으로 그룹화하고, `WHERE`가 그 결과인 `films`를 검사합니다. 같은 조건을
`MATCH ... WHERE`에 쓰면 `aggregate functions are not allowed in WHERE`로 거부됩니다.
{#with-add-a-column-without-losing-the-others}
### 다른 컬럼을 잃지 않고 컬럼 더하기
```cypher
MATCH (p:person)-[:directed]->(m:movie)
WITH *, m.year - p.born AS age_at_release
RETURN p.name AS director, m.title AS film, age_at_release
ORDER BY age_at_release
LIMIT 3;
```
```
director | film | age_at_release
-------------------+------------------+----------------
"James Cameron" | "The Terminator" | 30
"Lilly Wachowski" | "The Matrix" | 32
"Andrew Niccol" | "Gattaca" | 33
(3 rows)
```
`WITH *`가 `p`와 `m`을 유효 범위에 남기므로 `RETURN`이 그 속성을 계속 읽을 수 있습니다.
[`LET`](let.md)은 `*` 없이 같은 일을 합니다.
{#with-watch-what-a-with-drops}
### WITH가 무엇을 버리는지 보기
투영이 빼놓은 것은 그 뒤로 유효 범위 밖입니다:
```cypher
MATCH (p:person)-[:acted_in]->(m:movie)
WITH m
RETURN p.name;
```
```
ERROR: variable does not exist
LINE 1: ...ATCH (p:person)-[:acted_in]->(m:movie) WITH m RETURN p.name;
^
```
{#with-deduplicate-mid-pipeline}
### 파이프라인 도중에 중복 없애기
```cypher
MATCH (p:person)-[:acted_in]->(m:movie)
WITH DISTINCT m.genre AS genre
RETURN genre
ORDER BY genre;
```
```
genre
-------------
"Action"
"Adventure"
"Sci-Fi"
(3 rows)
```
{#with-cut-the-pipeline-down-before-matching-further}
### 더 일치시키기 전에 파이프라인 줄이기
`WITH` 뒤의 `ORDER BY`와 `LIMIT`은 다음 절이 다뤄야 하는 행 수를 줄입니다:
```cypher
MATCH (m:movie)
WITH m ORDER BY m.year DESC LIMIT 2
MATCH (p:person)-[:directed]->(m)
RETURN m.title AS film, p.name AS director
ORDER BY film;
```
```
film | director
----------------------------+--------------------
"Blade Runner 2049" | "Denis Villeneuve"
"The Matrix Resurrections" | "Lana Wachowski"
(2 rows)
```
가장 최근 영화 두 편만 둘째 `MATCH`에 도달합니다.
{#with-see-that-paging-follows-the-filter}
### 페이지 나누기가 필터 뒤에 오는 것 확인하기
`WHERE`는 `WITH`에 속하고, `ORDER BY`와 `LIMIT`은 그 뒤의 절입니다. 그래서 `LIMIT`은 필터를 통과한
행을 셉니다:
```cypher
MATCH (m:movie)
WITH m.title AS film, m.genre AS genre WHERE genre = 'Action'
ORDER BY film LIMIT 3
RETURN film, genre;
```
```
film | genre
------------------------------+----------
"Terminator 2: Judgment Day" | "Action"
"The Avengers" | "Action"
"The Matrix" | "Action"
(3 rows)
```
필터를 빼면 같은 페이지 나누기가 완전히 다른 행을 고릅니다. 이제 제목순으로 앞의 세 행이 남기
때문입니다:
```cypher
MATCH (m:movie)
WITH m.title AS film, m.genre AS genre
ORDER BY film LIMIT 3
RETURN film, genre;
```
```
film | genre
---------------------+----------
"Avatar" | "Sci-Fi"
"Blade Runner" | "Sci-Fi"
"Blade Runner 2049" | "Sci-Fi"
(3 rows)
```
{#with-reject-a-repeated-output-name}
### 같은 출력 이름은 거부된다
```cypher
MATCH (m:movie)
WITH m.title AS film, m.genre AS film
RETURN film;
```
```
ERROR: WITH passes on "film" more than once
LINE 1: MATCH (m:movie) WITH m.title AS film, m.genre AS film RETURN...
^
```
변수를 그대로 넘기면서 다른 것에 그 이름을 별칭으로 붙이는 것도 같은 식으로 충돌합니다.
`WITH m, m.title AS m`은 `WITH passes on "m" more than once`를 냅니다.
{#with-notes}
## 참고
`WHERE`는 투영 목록 바로 뒤, `ORDER BY`·`SKIP`·`LIMIT` 앞에 써야 합니다. 그보다 뒤에 두면 구문
오류입니다. `WITH ... ORDER BY film WHERE genre = 'Action'`은 파싱되지 않습니다.
{#with-see-also}
## 관련 항목
- [`RETURN`](return.md) — 쿼리를 끝내는, 같은 투영
- [`LET`](let.md) {bdg-primary-line}`GQL` — 어떤 바인딩도 버리지 않고 더하기
- [`WHERE`](where.md) — `WITH`가 지닐 수 있는 조건
- [`ORDER BY`](order-by.md), [`SKIP`·`LIMIT`](skip-and-limit.md) — `WITH` 뒤에 오는 절들
- [`UNWIND`](unwind.md) — `collect()`를 되돌릴 때의 흔한 짝