BigQuery Tutorial

SQL Joins in BigQuery: How to Combine Marketing Data Tables

Santiago Cardozo
Marketing Manager at Porter

March 19, 2026

A JOIN is the SQL operation that merges two or more tables based on a shared column. In BigQuery, you use JOINs to combine your marketing data sources: Meta Ads with Google Ads, ad data with CRM data, campaign data with revenue data.

Understanding JOINs is one of the most valuable SQL skills for marketing analysts. Here is how they work.

The Concept: Venn Diagrams and Sets

The easiest way to understand SQL JOINs is through Venn diagrams. A Venn diagram shows two sets (two circles) and the overlap between them.

Your two tables are the two circles. The shared column is what the circles have in common. The JOIN type determines which part of the Venn diagram you return.

There are four main JOIN types. Each returns a different portion of the combined data.

INNER JOIN: Only Matching Rows

An INNER JOIN returns only the rows that exist in both tables. If a row exists in Table A but not in Table B, it is excluded. If a row exists in Table B but not in Table A, it is also excluded.

SELECT
meta.date,
meta.campaign_name,
meta.spend AS meta_spend,
gads.cost AS google_spend
FROM your_dataset.meta_ads AS meta
INNER JOIN your_dataset.google_ads AS gads

ON meta.date = gads.date

AND meta.campaign_name = gads.campaign_name

This returns only rows where the same campaign name and date appear in both tables.

LEFT JOIN: All Rows From the Left Table

A LEFT JOIN returns all rows from the left table (the one in FROM) and the matching rows from the right table. If a row in the left table has no match in the right table, the right table columns appear as NULL.

SELECT
meta.date,
meta.campaign_name,
meta.spend AS meta_spend,
gads.cost AS google_spend
FROM your_dataset.meta_ads AS meta
LEFT JOIN your_dataset.google_ads AS gads

ON meta.date = gads.date

AND meta.campaign_name = gads.campaign_name

Campaigns that exist only in Meta Ads appear in the result with NULL in the google_spend column. This is the most common JOIN type for marketing data because you want to preserve all your campaigns, even those running on only one platform.

RIGHT JOIN: All Rows From the Right Table

A RIGHT JOIN is the mirror of a LEFT JOIN. It returns all rows from the right table and the matching rows from the left table. Rows in the right table with no match in the left table appear with NULL in the left table columns.

In practice, most analysts rewrite RIGHT JOINs as LEFT JOINs by swapping the table order. They are functionally equivalent.

FULL JOIN: All Rows From Both Tables

A FULL JOIN (also called FULL OUTER JOIN) returns all rows from both tables. Where there is a match, the columns from both tables are populated. Where there is no match, the columns from the missing side appear as NULL.

SELECT
COALESCE(meta.date, gads.date) AS date,
COALESCE(meta.campaign_name, gads.campaign_name) AS campaign_name,
meta.spend AS meta_spend,
gads.cost AS google_spend
FROM your_dataset.meta_ads AS meta
FULL JOIN your_dataset.google_ads AS gads

ON meta.date = gads.date

AND meta.campaign_name = gads.campaign_name

COALESCE returns the first non-NULL value from the list. This handles rows that exist in only one table by using the available value for date and campaign name.

Choosing the Right JOIN for Marketing Data

For most marketing data analysis, LEFT JOIN is the right choice. It preserves all your campaigns from the primary table and adds data from secondary tables where it exists.

Use INNER JOIN when you only want campaigns that exist in both tables and you want to exclude campaigns that are unique to one platform.

Use FULL JOIN when you want a complete view of all campaigns across all platforms, including those that run on only one platform.

Joining Ad Data With CRM Data

JOINs become especially valuable when you combine ad performance data with CRM or revenue data.

SELECT

ads.date,

ads.campaign_name,

ads.spend,

ads.leads AS ad_reported_leads,

crm.qualified_leads,

crm.revenue,

ROUND(ads.spend / NULLIF(crm.revenue, 0), 2) AS true_roas

FROM your_dataset.meta_ads AS ads

LEFT JOIN your_dataset.hubspot_data AS crm

ON ads.campaign_name = crm.utm_campaign

AND ads.date = crm.date

This query joins Meta Ads spend data with HubSpot CRM data on campaign name and date. The result shows true ROAS calculated from actual revenue, not platform-reported conversion value.

This type of analysis is only possible in BigQuery, where all your data lives in one place and you control the JOIN logic.

← Previous Lesson
Next Lesson →

Ready to connect your marketing data to BigQuery?

Porter Metrics makes it easy to sync all your sources — no code required.

Start Free Trial