SQL Libraries: Define Once, Compose

Concept. A library packages the SQL you repeat as named, parameterized queries, so you define a term once and compose it everywhere. Each definition fixes a subtle choice once, what "a listen" means or how a NULL counts, so every question built on it computes the same way. This is ordinary SQL engineering: a team builds a governed layer of definitions.

Intuition. Define listener_of(artist) and active_since(days) once. "Active Beatles listeners" is active_since(7) ∩ listener_of('Beatles'), composed from the two, never rewritten.

Define Once, Compose

A team could ask the same question a hundred times. Alice calls a user active if they listened this week, Bob counts the last thirty days, and an LLM drafting the query picks a third rule: three dashboards, three definitions of "active user." The fix is the one software uses for any repeated code, a library. Write each definition once as a named, parameterized query (in Postgres, a table-valued function) and call it by name.

-- definitions.sql: each term is a named function you compose by name.

-- Step 1: Listener of an artist
CREATE FUNCTION listener_of(artist TEXT) RETURNS TABLE(user_id INT) AS $$
  SELECT DISTINCT l.user_id
  FROM Listens l JOIN Songs s ON l.song_id = s.song_id
  WHERE s.artist = listener_of.artist          -- the parameter, qualified
$$ LANGUAGE sql;

-- Step 2: Active in a recent window
CREATE FUNCTION active_since(days INT) RETURNS TABLE(user_id INT) AS $$
  -- a day follows the database session's calendar boundary, not a rolling 24h;
  -- a NULL listen_time never counts as active.
  SELECT DISTINCT user_id FROM Listens
  WHERE listen_time >= CURRENT_DATE - days
$$ LANGUAGE sql;

-- Step 3: Liked at or above a rating
CREATE FUNCTION liked(min_rating NUMERIC) RETURNS TABLE(user_id INT, song_id INT) AS $$
  -- a NULL rating is not a like, so Daffy's unrated play drops out.
  SELECT DISTINCT user_id, song_id FROM Listens
  WHERE rating >= min_rating
$$ LANGUAGE sql;

Each comment records a choice the definition fixes once, so every query that uses it inherits the same answer. The name is the interface: active_since(7) ∩ listener_of('Beatles') means "active Beatles listeners" without re-deriving either term. A CTE names a query inside one statement; a library keeps its definitions for every query.

What a Library Spans

A handful of definitions is small, but it composes into a large space of questions.

A DEFINED panel of three parameterized primitives (listener_of, active_since, liked) composes into a large green ANSWERABLE region of questions, none written out: All minus listener_of('Taylor'), active_since(7) intersect listener_of('Beatles'), listener_of('Taylor') intersect liked(4.0). A dashed power_user chip sits in the DEFINED set as the primitive you add next, and adding it unlocks a new dashed green composition. Past a hard boundary is a grey OFF THE TABLE region: subjective, missing-data, or predictive questions.

Figure 1. Composing verified terms keeps the answer verified: active_since(7) ∩ listener_of('Beatles') answers "active Beatles listeners." A gap like "power users" closes with one new definition; off the table questions ("which songs are good," "will Daffy churn") no definition can reach, because the answer is not in the data.