Marketing Cloud SQL Cheat Sheet

The rules, patterns and data view joins you need for Marketing Cloud Query Activities, with short sample queries you can adapt and test in your own account.

Type
Resource
Topic
Resource
Reading time
4 min
Updated
Author
GeekMidst Team
Reviewed by
Site owner
Talk to an expert
Cover of the GeekMidst Marketing Cloud SQL Cheat Sheet (cheat sheet), listing sections: The rules that matter, System data views at a glance, Sends by journey

Marketing Cloud Engagement runs SQL through Query Activities in Automation Studio. The dialect is a subset of T-SQL, and the way it runs is different from a normal database: every query is a single SELECT whose results are written into a target data extension. This sheet covers the rules that trip people up and the patterns that come up most often.

The rules that matter

  • One SELECT per activity. No UPDATE, DELETE or INSERT statements, variables, temporary tables or cursors. The data action on the activity (Overwrite, Update or Append) decides what happens in the target.
  • Every output column needs a name that matches a field in the target data extension. Alias calculated columns with AS.
  • Primary keys in the target are enforced. Duplicate key values in your results cause the activity to fail, so deduplicate before writing.
  • Field lengths and types must fit. A 300-character value into a 255-character field fails the run.
  • There is a run-time limit. Long-running queries are stopped. Check current limits for your account in Salesforce Help and split heavy logic into staged queries.
  • Dates use system time, which is Central Standard Time without daylight saving adjustment.
  • Data extension names with spaces or hyphens need square brackets, for example [Orders - Staging].

System data views give you send and engagement history without building your own tracking extracts. They keep a limited rolling window of history and some are only available in certain business unit contexts, so check current retention and availability in Salesforce Help and copy what you need for long-term reporting into your own data extensions.

System data views at a glance

Data viewHoldsUseful fields
_SentOne row per email sentSubscriberKey, JobID, EventDate, TriggererSendDefinitionObjectID
_OpenOpen eventsSubscriberKey, JobID, EventDate, IsUnique
_ClickClick eventsSubscriberKey, JobID, EventDate, URL, IsUnique
_BounceBounce eventsSubscriberKey, Domain, BounceCategory, SMTPBounceReason
_UnsubscribeUnsubscribe eventsSubscriberKey, JobID, EventDate
_JobSend job detailsJobID, EmailName, DeliveredTime
_SubscribersAll Subscribers listSubscriberKey, EmailAddress, Status
_Journey and _JourneyActivityJourney versions and their activitiesVersionID, JourneyName, JourneyActivityObjectID
sql
SELECT SubscriberKey, EmailAddress, LastPurchaseDate
FROM (
    SELECT
        SubscriberKey,
        EmailAddress,
        LastPurchaseDate,
        ROW_NUMBER() OVER (
            PARTITION BY SubscriberKey
            ORDER BY LastPurchaseDate DESC
        ) AS rn
    FROM Customers_Staging_DE
) x
WHERE x.rn = 1
Keep the most recent row per SubscriberKey before writing to a keyed target
sql
SELECT c.SubscriberKey, c.EmailAddress
FROM Customers_DE c
WHERE NOT EXISTS (
    SELECT 1 FROM _Open o
    WHERE o.SubscriberKey = c.SubscriberKey
      AND o.EventDate >= DATEADD(day, -90, GETDATE())
)
AND NOT EXISTS (
    SELECT 1 FROM _Click k
    WHERE k.SubscriberKey = c.SubscriberKey
      AND k.EventDate >= DATEADD(day, -90, GETDATE())
)
Customers with no opens or clicks in the last 90 days

Sends by journey

To report on which journey sent which email, join _Sent to _JourneyActivity on the triggered send definition, then to _Journey on the version. The example assumes a target data extension Journey_Sends_DE with matching fields.

sql
SELECT
    j.JourneyName,
    j.VersionNumber,
    ja.ActivityName,
    s.SubscriberKey,
    s.EventDate AS SentDate
FROM _Sent s
INNER JOIN _JourneyActivity ja
    ON s.TriggererSendDefinitionObjectID = ja.JourneyActivityObjectID
INNER JOIN _Journey j
    ON ja.VersionID = j.VersionID
WHERE s.EventDate >= DATEADD(day, -7, GETDATE())
Last seven days of journey email sends

Quick patterns

NeedPattern
Join strings safelyISNULL(FirstName, '') + ' ' + ISNULL(LastName, '') AS FullName
Default a missing valueCOALESCE(PreferredStore, HomeStore, 'Online') AS Store
Bucket valuesCASE WHEN Points >= 1000 THEN 'Gold' ELSE 'Standard' END AS Tier
Date only, no timeCONVERT(date, OrderDate) AS OrderDay
Last N daysWHERE EventDate >= DATEADD(day, -30, GETDATE())
Unique opens onlyWHERE o.IsUnique = 1
Case-insensitive email matchWHERE LOWER(a.EmailAddress) = LOWER(b.EmailAddress), although the default collation is usually case-insensitive already

Stage heavy logic

If one query joins several large data views, filters on dates and deduplicates all at once, it is more likely to hit the run-time limit and harder to debug. Split it into steps inside one automation: first copy the last 30 days of _Sent into a staging data extension, then join that smaller set to opens and clicks, then deduplicate into the final target. Each step can be checked on its own, and a failure tells you which stage broke. Give staging extensions a clear naming convention, such as a _STG suffix, and overwrite them on each run so they do not grow without limit.

Diagnosing failures

When a Query Activity fails, check in this order: the target field names and lengths, duplicate primary keys in the results, data types (text compared with numbers or dates), and run time. Validate the query in the activity editor, then run it into a test data extension with no primary key to inspect the raw output.

More detail: Marketing Cloud SQL query activity errors, deduplicating records with ROW_NUMBER, using data views for engagement reporting and our Marketing Cloud SQL development service.

Queries timing out or failing?

We design, tune and document Marketing Cloud SQL and the automations that run it.

Get help with Marketing Cloud SQL →

Tell us what you are trying to fix.

Share your Salesforce setup, goals and constraints. A practitioner reads every message and replies with questions, first thoughts or an honest view of whether you need outside help at all.

Talk to a Salesforce Expert
Book a Consultation