SQL Filter Early

Cut down the row count as early as possible — every downstream step has less work to do.

What & Why

Filtering early — inside a CTE, before a join, in the innermost subquery — reduces how much data every subsequent step has to process. The planner often reorders things for you, but writing filters early makes the intent explicit and helps in cases the planner can't reorder automatically.

See How It Works

BUSINESS QUESTION

Marketing wants converted leads filtered before they are joined to active campaigns.

idcampaign_idemailcreated_atqualified_atconverted_atlead_scoresourcecountry
3011ana@example.com2024-01-21 09:10:00+002024-01-22 11:00:00+002024-02-02 10:00:00+0086google_adsUS
3021ben@example.com2024-01-24 12:40:00+00NULLNULL52google_adsCA
3032chloe@example.com2024-02-16 08:30:00+002024-02-18 14:20:00+00NULL74emailGB
3043dev@example.com2024-03-20 17:15:00+002024-03-21 09:00:00+002024-04-04 16:00:00+0091linkedinUS
idnamechannelspendstart_dateend_datestatustarget_segment
1Spring Launchgoogle_ads55000.002024-01-152024-03-31activesmb
2Retention Webinaremail45000.002024-02-102024-04-15activeenterprise
3Finance Retargetinglinkedin50000.002024-03-122024-05-31activeenterprise
4Enterprise Searchgoogle_ads60000.002024-04-012024-06-30activeenterprise
EXAMPLE QUERY
WITH converted_leads AS (
  SELECT id, campaign_id
  FROM marketing.leads
  WHERE converted_at IS NOT NULL
    AND converted_at >= TIMESTAMPTZ '2024-01-01 00:00:00+00'
)
SELECT
  c.id AS campaign_id,
  c.name,
  COUNT(l.id) AS conversions
FROM converted_leads l
JOIN marketing.campaigns c ON c.id = l.campaign_id
WHERE c.status = 'active'
GROUP BY c.id, c.name
ORDER BY conversions DESC, campaign_id;
RESULT — active campaigns with conversions
campaign_idnameconversions
1Spring Launch1
3Finance Retargeting1

The CTE filters to the two converted leads before joining them to their active campaigns.

This lesson's practice is part of Pro.

Advanced business practice

Sign up free to try it on a real business scenario