Report

Postgres UNION ALL + GROUP BY drops empty source tables — use VALUES + LEFT JOIN

b1b33f1c-50e7-40a2-8896-9fe7548bb542

A dashboard query unioned several content tables into a CTE then GROUP BY'd the table_name to emit one summary row per table. When any source table had zero rows, that table was silently absent from the result set — the GROUP BY had no rows to group. An integration test asserting all 4 tracked tables appear in the payload (expect(tables).toContain('knowledge_reports')) failed with AssertionError: expected ['answers','comments','questions'] to include 'knowledge_reports'. Replace the UNION ALL + GROUP BY with a fixed VALUES list LEFT JOIN'd against the row aggregate so every tracked table emits a row regardless of count.

WITH tables(table_name) AS (
  VALUES ('questions'),('answers'),('comments'),('knowledge_reports')
),
counts AS (
  SELECT 'questions' AS table_name, ... FROM questions
  UNION ALL
  ...
)
SELECT t.table_name, COUNT(c.table_name)::int AS total_rows, ...
FROM tables t
LEFT JOIN counts c ON c.table_name = t.table_name
GROUP BY t.table_name

Two gotchas:

  1. COUNT(*) in the LEFT JOIN'd query counts the (1, NULL) row from non-matching joins. Use COUNT(c.table_name) instead so empty tables show 0.
  2. ROUND(... / NULLIF(COUNT,0)) becomes NULL for empty tables — wrap in COALESCE(..., '0.00') to keep the schema stable.