โ† Back to list

๐Ÿ“ˆ Dynamic Year-over-Year Trend Comparison in CRMA

Have you ever needed to compare year-over-year performance trendsโ€Šโ€”โ€Šsay by month or quarterโ€Šโ€”โ€Šwithout hardcoding the year labels? In thisโ€ฆ

Ada Xu ยท 2025-07-06 17:22 ยท 0 claps ยท 2.7 min read
#saql #einstein-analytics #crm-analytics
Open on Medium โ†—
Wiki topics: GRW ยท Growth & Analytics ๐Ÿ’ป ยท Programming

๐Ÿ“ˆ Dynamic Year-over-Year Trend Comparison in CRMA

Have you ever needed to compare year-over-year performance trends โ€” say by month or quarter โ€” without hardcoding the year labels? In this post, Iโ€™ll show you how to build a dynamic YoY comparison chart in CRMA using SAQL, with fully auto-updating labels like โ€œ2025โ€, โ€œ2024โ€, and โ€œ2023โ€.

Use Case: Monthly Sales Review Over the Past 3 Years

Imagine youโ€™re a Sales Analyst supporting your Field Sales team. Your stakeholders want to see how many Sales were completed in each month โ€” comparing the past three years (2023, 2024, 2025).

But hereโ€™s the twist:

  • They want a trend line chart (month on the x-axis, count on the y-axis).
  • They want the labels to automatically update next year, i.e., show 2026, 2025, 2024, without you manually editing the dashboard or query.
  • And of course, they want it fast and clean.

Why Not Just Group by Year and Month?

If you just use Year-Month and sum sales, your chart will be a long spaghetti line with 30+ data points. Itโ€™s messy and hard to compare trends between years.

Instead, we separate the data into three streams, each for one year, and align them by Month (or Week or Quarter). This allows you to create a clean, layered comparison chart, with one line per year.

SAQL Code (Basic Version with Hardcoded Labels)

q = load "Sales";
q_B = filter q by date('Date_Year', 'Date_Month','Date_Day') in ["current year".."current day"];
q_C = filter q by date('Date_Year', 'Date_Month','Date_Day') in ["1 year ago".."1 year ago"];
q_D = filter q by date('Date_Year', 'Date_Month','Date_Day') in ["2 years ago".."2 years ago"];
q = cogroup q_B by 'Date_Month' full, 
             q_C by 'Date_Month' full, 
             q_D by 'Date_Month';
q = foreach q generate coalesce(q_B.'Date_Month', q_C.'Date_Month', q_D.'Date_Month') as 'Month'
  , sum(q_B.'Weekly_Sales') as '2025',  sum(q_C.'Weekly_Sales') as '2024'
  ,  sum(q_D.'Weekly_Sales') as '2023';

Use a Combo chart type

Use a Combo chart type

Problem: Hardcoding Year Labels Is Fragile

This works now. But next year? You have to go in and manually update those labels again. Thatโ€™s not scalable.

What we really need is a dynamic label binding โ€” so the labels always show the correct years based on todayโ€™s date.

SAQL Strategy Overview

Hereโ€™s the strategy I used:

  1. Filter 3 separate datasets by year: current year, last year, two years ago.
  2. Cogroup the datasets by time granularity (month, week, or quarter).
  3. Use a dynamic binding to fetch the year values from another step (say, a table query).
  4. Label each yearโ€™s measure dynamically.

The SAQL Code with Dynamic Year Labels

Hereโ€™s a simplified version of the SAQL:

q = load "Sales";
q_B = filter q by date('Date_Year', 'Date_Month','Date_Day') in ["current year".."current day"];
q_C = filter q by date('Date_Year', 'Date_Month','Date_Day') in ["1 year ago".."1 year ago"];
q_D = filter q by date('Date_Year', 'Date_Month','Date_Day') in ["2 years ago".."2 years ago"];
q = cogroup q_B by 'Date_Month' full, 
             q_C by 'Date_Month' full, 
             q_D by 'Date_Month';
q = foreach q generate coalesce(q_B.'Date_Month', q_C.'Date_Month', q_D.'Date_Month') as 'Month'
    , sum(q_B.'Weekly_Sales') as '{{cell(Year_Binding_1.result, 2, "Date_Year").asString()}}'
    , sum(q_C.'Weekly_Sales') as '{{cell(Year_Binding_1.result, 1, "Date_Year").asString()}}'
    , sum(q_D.'Weekly_Sales') as '{{cell(Year_Binding_1.result, 0, "Date_Year").asString()}}';

Year_Binding_1: Dynamic Year List

Create a simple query step (e.g., a table) named Year_Binding_1, that lists the past 3 years dynamically. You can definitely just do the compact format. It translate something like this is SAQL:

q = load "your_dataset";
q_A = filter q by date('Date_Year', 'Date_Month', 'Date_Day') 
      in ["current year".."current day"];
q_B = filter q by date('Date_Year', 'Date_Month', 'Date_Day') 
      in ["1 year ago".."1 year ago"];
q_C = filter q by date('Date_Year', 'Date_Month', 'Date_Day') 
      in ["2 years ago".."2 years ago"];
q = cogroup q_B by 'Date_Year' full, q_C by 'Date_Year' full, q_D by 'Date_Year';
q = foreach q generate 
    coalesce(q_A.'Date_Year'๏ผŒ q_B.'Date_Year'๏ผŒq_C.'Date_Year') as 'Date Year';

This step doesnโ€™t need to be shown in your dashboard โ€” it just powers the binding.

Benefits

  • ๐Ÿ“… Auto-updating labels: Future-proof your dashboard.
  • โš™๏ธ No code changes next year: Save maintenance time.
  • ๐Ÿงน Cleaner chart: No cluttered or hardcoded titles.
  • ๐Ÿง  Reusable technique: Apply this to quarters, weeks, or other categories.

โ˜€๏ธEnjoy SAQL! โ˜€๏ธ


๋ฉ”ํƒ€๋ฐ์ดํ„ฐ
post_id
c00a70bf43d2
slug
dynamic-year-over-year-trend-comparison-in-crma-c00a70bf43d2
url
https://medium.com/@adaxu2018/dynamic-year-over-year-trend-comparison-in-crma-c00a70bf43d2
canonical_url
https://medium.com/@adaxu2018/dynamic-year-over-year-trend-comparison-in-crma-c00a70bf43d2
author_url
https://medium.com/@adaxu2018
status
ok
fetched_at
2026-09-07 05:43:49