Skip to Content
0 likes
Turn Rows Into Columns With FILTER Level: Intermediate

Turn one row per status into one column per status with aggregate FILTER and compare it with CASE. After this, you can build a small pivot table without an extension.

0 likes
Running Total With a Window Function Level: Intermediate

Add a running total with SUM and OVER, restart it for each group and avoid the default-frame surprise when dates tie. After this, a cumulative column is one line and not a self-join.

0 likes
Verify a CTE Rewrite Without Losing Duplicate Rows Level: Intermediate

Compare a query and its CTE rewrite in both directions with EXCEPT ALL, including duplicate and NULL rows that a plain set comparison can miss.

0 likes
Store Timestamps With Time Zone Correctly Level: Intermediate

Choose timestamptz for a moment in time and see what the session time zone and AT TIME ZONE change. After this, the same moment shows correctly for every reader.

0 likes
Top 3 Rows per Group Level: Intermediate

Rank rows inside each group and keep the first three, then decide what to do with ties and compare the LATERAL version. After this, you can pick the top rows per category and know what happens when two are equal.

0 likes
Upsert With INSERT … ON CONFLICT Level: Intermediate

Insert a row or update the one that is already there in a single statement, using the conflict target, DO NOTHING, DO UPDATE and the EXCLUDED row. After this, a repeated import updates rows instead of failing or duplicating them.

0 likes
Read EXPLAIN ANALYZE in 10 Minutes Level: Advanced

Run one slow query with EXPLAIN ANALYZE and read it with a five-question checklist: rows touched, filtered rows, estimates, loops and sort spills. After this, you can find the slow node of a plan and check your fix.

0 likes
Find Slow Queries With pg_stat_statements Level: Advanced

Turn on pg_stat_statements in a Docker container and list the statements that cost the most in total. After this, you know which query to tune first, and you do not have to guess.

0 likes
Create an Index Without Blocking Writes Level: Advanced

Build an index with CREATE INDEX CONCURRENTLY while a writer is active, and handle the transaction-block error and the invalid index that a failed build leaves. After this, you can add an index to a busy table without stopping its writers.

0 likes
Partial Index for Active Rows Only Level: Advanced

Index only the rows that queries ask for, compare the size with a full index, and enforce a unique rule for active rows. After this, you know why a prepared statement can ignore a partial index, and how to avoid it.

0 likes
Index a JSONB Column With GIN Level: Advanced

Add a GIN index to a JSONB column, filter with the contains operator, and compare it with an expression index and jsonb_path_ops. After this, you can tell which JSONB filters use an index and which scan the table.

0 likes
Find Unused and Duplicate Indexes Level: Advanced

Read pg_stat_user_indexes to find indexes that were never scanned, find identical indexes in pg_index, and drop them with DROP INDEX CONCURRENTLY. After this, you can remove indexes that cost writes and give nothing back.