Learn SQL/Intermediate/Joins/SQL JOINs with Comparison Operators

SQL JOINs with Comparison Operators

A join condition doesn't have to be equality — >, <, >=, and <= all work perfectly well inside ON, opening up genuinely useful matching patterns.

What & Why

Every join so far in this series has matched rows using = — an "equi-join." Nothing about ON requires that. Any condition that evaluates to true or false is valid, including >, <, >=, and <=.

See How It Works

BUSINESS QUESTION

Attach campaigns that were active when each lead was created.

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
SELECT
  l.id AS lead_id,
  c.name AS campaign_name,
  l.created_at
FROM marketing.leads l
JOIN marketing.campaigns c
  ON l.created_at::date BETWEEN c.start_date AND COALESCE(c.end_date, DATE '2024-12-31')
ORDER BY lead_id, campaign_name;
RESULT — exact output from the displayed Queryflo rows
lead_idcampaign_namecreated_at
301Spring Launch2024-01-21 09:10:00+00
302Spring Launch2024-01-24 12:40:00+00
303Retention Webinar2024-02-16 08:30:00+00
303Spring Launch2024-02-16 08:30:00+00
304Finance Retargeting2024-03-20 17:15:00+00
304Retention Webinar2024-03-20 17:15:00+00
304Spring Launch2024-03-20 17:15:00+00

The range predicate can match one lead date to several overlapping campaign windows.

Now You Try

Practice this concept

Return every lead-campaign date-range match from the displayed Queryflo rows, ordered by lead_id and campaign_name.

Available schema
marketing

Prefix tables with marketing.table_name.

lead_idcampaign_namecreated_at
marketing.campaigns
ColumnType
idinteger
nametext
channeltext
spendnumeric
start_datedate
end_datedate
statustext
target_segmenttext
legacy_idtext
marketing.leads
ColumnType
idinteger
campaign_idinteger
emailtext
created_attimestamp with time zone
qualified_attimestamp with time zone
converted_attimestamp with time zone
lead_scoreinteger
sourcetext
countrytext
archive_statustext
query.sql
Intermediate business practice

Sign up free to try it on a real business scenario