WITH#
작업 행을 새 컬럼 집합으로 투영해 다음 절에 넘깁니다. 파이프라인 가운데에 있는 RETURN입니다.
개요#
굵게 키워드 · 기울임 직접 채우는 자리 · [ ] 생략 가능 · ... 반복 가능. 구문 표기 규약을 참고하십시오.
설명#
WITH는 파이프라인의 한 구역을 닫고 다음 구역을 엽니다. RETURN과 정확히 같은
방식으로 행마다 표현식을 평가하고, 그 결과 컬럼을 뒤따르는 절에 넘깁니다. 세 가지 일에 이것이
필요합니다:
집계한 다음 걸러 내거나 더 일치시키기. 집계 함수는
WHERE에 올 수 없으므로,WITH에서 집계하고 그 출력을 걸러 내십시오.값을 한 번만 계산해 뒤따르는 여러 절에서 쓰기.
쿼리의 비싼 부분이 실행되기 전에
DISTINCT·ORDER BY·LIMIT으로 파이프라인을 줄이기.
이것이 투영이라는 점에서 따라오는 규칙들입니다:
WITH는 유효 범위를 교체합니다. 투영한 것만 살아남습니다. 빼놓은 변수는 사라지고, 그것을 뒤에서 언급하면variable does not exist가 나옵니다. 버리지 않고 더하려면WITH *, expr AS v로 쓰거나LET을 쓰십시오.각 출력 이름은 그 절 안에서 고유해야 합니다. 같은 이름을 두 번 투영하면
WITH passes on "..." more than once가 나옵니다.RETURN에는 그런 규칙이 없습니다.이 절의
WHERE는 투영과 집계가 끝난 뒤에 실행되므로, 집계의 별칭을 검사할 수 있습니다.ORDER BY,SKIP/OFFSET,LIMIT은WITH뒤에 오는 별개의 절이고, 따라서 그WHERE뒤에도 옵니다. 필터가 먼저 실행되고, 페이지 나누기는 살아남은 것에 적용됩니다.WITH는 쿼리를 시작할 수도, 끝낼 수도 없습니다. 문장 맨 앞의WITH는 SQL의 공통 테이블 표현식이고, 그것은 이름과 괄호로 감싼 쿼리를 받는 다른 절입니다.LET에는 그런 충돌이 없어서 쿼리를 시작할 수 있습니다.
매개변수#
- DISTINCT
투영한 행을 넘기기 전에 중복 행을 없앱니다.
- ALL
중복 행을 그대로 둡니다. 기본값입니다.
- *
유효 범위의 이름 있는 모든 바인딩을 그대로 통과시킵니다.
WITH *, expr AS v처럼 다른 항목과 함께 쓰면 어떤 컬럼도 버리지 않고 컬럼을 더할 수 있습니다.- expression
유효 범위의 바인딩에 대한 Cypher 표현식이면 무엇이든 되고, 집계 함수도 됩니다.
- alias
다음 절이 쓰는 이름입니다. 변수 참조만 있는 것이 아니라면 필수입니다. 뒤따르는 절이 그것을 이름으로 부를 수 있어야 하기 때문입니다.
- condition
투영된 행을 걸러 내는 불리언 표현식입니다. 투영 뒤에 평가되므로 이 절에서 정의한 별칭을 가리킬 수 있습니다.
예제#
모든 예제는 예제 데이터셋에서 실행됩니다.
개수로 걸러 내기#
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로 거부됩니다.
다른 컬럼을 잃지 않고 컬럼 더하기#
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은 * 없이 같은 일을 합니다.
WITH가 무엇을 버리는지 보기#
투영이 빼놓은 것은 그 뒤로 유효 범위 밖입니다:
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;
^
파이프라인 도중에 중복 없애기#
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 뒤의 ORDER BY와 LIMIT은 다음 절이 다뤄야 하는 행 수를 줄입니다:
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에 도달합니다.
페이지 나누기가 필터 뒤에 오는 것 확인하기#
WHERE는 WITH에 속하고, ORDER BY와 LIMIT은 그 뒤의 절입니다. 그래서 LIMIT은 필터를 통과한
행을 셉니다:
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)
필터를 빼면 같은 페이지 나누기가 완전히 다른 행을 고릅니다. 이제 제목순으로 앞의 세 행이 남기 때문입니다:
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)
같은 출력 이름은 거부된다#
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를 냅니다.
참고#
WHERE는 투영 목록 바로 뒤, ORDER BY·SKIP·LIMIT 앞에 써야 합니다. 그보다 뒤에 두면 구문
오류입니다. WITH ... ORDER BY film WHERE genre = 'Action'은 파싱되지 않습니다.