G·Graph Daily Lab 전체 140회
추가 13 / 40 · 보충 · 약 12분

OPTIONAL MATCH와 비어 있는 자리

패턴이 맞지 않는 행을 버리지 않고 null로 채워 남기는 OPTIONAL MATCH와, 그 null이 집계와 필터에서 어떻게 움직이는지 봅니다.

Cypher와 GQL

배운 뒤 돌아올 회차

DAY 31·32에서 MATCH와 WHERE를 배운 뒤, 관계가 없는 노드가 결과에서 조용히 사라지는 문제를 다루러 옵니다.

시작하면 직접 풀기와 퀴즈 기록이 저장됩니다. 본과정 100회 진도와는 별도입니다.

이번에 더 배울 것

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처럼 써야 합니다.

작은 예제로 따라가기

1

사람별 논문이 민수 2, 지아 2, 서준 1, 하린 1, 도윤 1, 유나 0편이면 MATCH를 두 번 쓴 질의는 7행을 내고 유나는 없습니다.

2

두 번째 MATCH를 OPTIONAL MATCH로 바꾸면 7행에 유나의 null 행이 더해져 8행이 됩니다.

3

사람별 count(x)는 유나 0이고, count(*)는 유나 1입니다.

COMPARE & EXPLAIN

같은 질문, 네 가지 쓰기

논문 연도가 P1 2019, P2 2021, P3 2023, P4 2022일 때, 각 쿼리에서 유나가 결과에 나오는지와 전체 행 수를 먼저 예상하세요.

7행, 유나 없음

두 번째 MATCH에서 유나는 일치하는 패턴이 없어 행 자체가 사라집니다.

OPTIONAL MATCH는 행을 지키고 빈자리를 null로 채우므로, 집계 함수와 WHERE의 위치를 null 기준으로 다시 확인합니다.

학습을 시작하면 새 문제를 직접 풀고 확인 퀴즈를 마친 뒤 선택한 본과정 회차로 돌아갑니다.