From 5f51c10ae876ac4397b680e509aeb2acd26e48a7 Mon Sep 17 00:00:00 2001 From: Rudy Celekli Date: Tue, 29 Sep 2026 20:10:47 -0400 Subject: [PATCH] Preserve empty comment arrays in Database Optimizer example --- engineering/engineering-database-optimizer.md | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/engineering/engineering-database-optimizer.md b/engineering/engineering-database-optimizer.md index 3af7da68..fa4f3e18 100644 --- a/engineering/engineering-database-optimizer.md +++ b/engineering/engineering-database-optimizer.md @@ -73,16 +73,23 @@ SELECT * FROM comments WHERE post_id = ?; EXPLAIN ANALYZE SELECT p.id, p.title, p.content, - json_agg(json_build_object( - 'id', c.id, - 'content', c.content, - 'author', c.author - )) as comments + COALESCE( + json_agg(json_build_object( + 'id', c.id, + 'content', c.content, + 'author', c.author + ) ORDER BY c.id) FILTER (WHERE c.id IS NOT NULL), + '[]'::json + ) AS comments FROM posts p LEFT JOIN comments c ON c.post_id = p.id WHERE p.user_id = 123 GROUP BY p.id; +-- Regression cases: no comments => []; two comments => two ordered objects. +-- FILTER removes the synthetic NULL row from LEFT JOIN; COALESCE turns an +-- empty aggregate into the same array shape as a populated one. + -- Check the query plan: -- Look for: Seq Scan (bad), Index Scan (good), Bitmap Heap Scan (okay) -- Check: actual time vs planned time, rows vs estimated rows