이번에 더 배울 것
MATCH는 모양이 맞는 것만 남깁니다. MATCH (p:Person) MATCH (p)-[:AUTHORED]->(x:Paper) RETURN p.name, x.title을 실행하면 논문이 없는 유나는 결과에 나오지 않습니다. OPTIONAL MATCH는 일치가 없을 때 패턴의 빈 부분을 null로 채우고 행을 남깁니다. Neo4j 문서는 이를 SQL의 외부 조인(outer join)에 해당한다고 설명합니다.
null은 집계에서 차이를 만듭니다. MATCH (p:Person) OPTIONAL MATCH (p)-[:AUTHORED]->(x:Paper) RETURN p.name, count(x)에서 유나는 0이 됩니다. count(식)은 null을 건너뛰기 때문입니다. 같은 자리에 count(*)를 쓰면 유나의 null 행도 한 행으로 세어 1이 나옵니다. collect(x.title)도 null을 넣지 않아 빈 목록이 됩니다.
WHERE의 위치도 중요합니다. OPTIONAL MATCH 바로 뒤의 WHERE는 그 패턴의 일부라서, 조건을 통과하지 못한 일치는 행을 지우지 않고 null로 남깁니다. 결과 행을 실제로 거르려면 WITH 뒤에 WHERE를 씁니다. 그래서 ‘논문이 없는 사람’을 OPTIONAL MATCH ... WHERE x IS NULL로 찾으려 하면 모든 사람이 나옵니다. WITH p, count(x) AS n WHERE n = 0처럼 써야 합니다.
작은 예제로 따라가기
사람별 논문이 민수 2, 지아 2, 서준 1, 하린 1, 도윤 1, 유나 0편이면 MATCH를 두 번 쓴 질의는 7행을 내고 유나는 없습니다.
두 번째 MATCH를 OPTIONAL MATCH로 바꾸면 7행에 유나의 null 행이 더해져 8행이 됩니다.
사람별 count(x)는 유나 0이고, count(*)는 유나 1입니다.
같은 질문, 네 가지 쓰기
논문 연도가 P1 2019, P2 2021, P3 2023, P4 2022일 때, 각 쿼리에서 유나가 결과에 나오는지와 전체 행 수를 먼저 예상하세요.
두 번째 MATCH에서 유나는 일치하는 패턴이 없어 행 자체가 사라집니다.
학습을 시작하면 새 문제를 직접 풀고 확인 퀴즈를 마친 뒤 선택한 본과정 회차로 돌아갑니다.