Drive Decisions Faster: The New Era of Period-Over-Period Analysis in Looker

Period-over-period (PoP) analysis – whether you’re looking at year-over-year, quarter-over-quarter, or month-over-month trends – is the bedrock of strategic decision-making. But in Looker doing PoP analysis has previously required the use of complex workarounds using LookML.

We’re excited to share that a new, streamlined approach to period-over-period analysis is here, and it’s designed to cut through the complexity and empower you with clear, actionable insights faster than ever before. The new period_over_period measure type in Looker is available now in Preview!

The new period_over_period measure type is flexible and easy to implement by defining a few straightforward parameters in LookML. Here’s what a new period_over_period measure looks like:

measure: orders_last_year_percent_change {
    type: period_over_period
    based_on: orders.count
    based_on_time: orders.created_year
    period: year
    kind: relative_change
    value_format_name: percent_2
  }

The measure above would be used to analyze the percent change in number of orders year over year. There are four new parameters that need to be defined as part of a period_over_period measure:

based_on: This should reference an existing LookML measure. In the example above, we are looking at order counts year over year, so this PoP measure is based on the orders.count measure. The referenced measure should be one of the following types: AVG, SUM, MAX, MIN, COUNT or DISTINCT.

period: A Looker timeframe interval value representing the cadence of the measure. This could be Year, fiscal_year, quarter, fiscal_quarter, month, week, or date. For a year-over-year comparison, this parameter should be set to year.

based_on_time: A LookML field of type time that should be the basis of your PoP comparison. In our example, we are comparing orders year over year, so we use orders.created_year as the based_on_time. This field can use any of the various time frames from a time based dimension group.

kind: This parameter indicates the type of PoP analysis that you want to do and should be one of the following values:

previous: The value from the previous period.

difference: Subtract the previous period from the current period.

relative_change: (current period - previous period)/ previous period

The new period-over-period measure type will adapt to the timeframes that are selected in the Explore query. This means that you can compare values for the entire year over another year, but also compare equivalent months across years. For the example above, if we take that same year-over-year relative_change PoP measure and imagine that someone is using it in the Explore and the Explore query contains the orders.created_month timeframe dimension, the PoP measure will calculate relative_change of the monthly values and compare them across years (e.g. compare the relative_change of May 2023 vs May 2022).

![flights_YoY.gif|1920x1003](upload://zI6OzwXD6UzIsTyoUlEjVR4Srxw.gif)

In this gif I start off by selecting a PoP measure for year-over-year relative change for flight count. I then select the flight arrival yearly time dimension and add in a dimension for destination. My PoP measure dynamically adapts the calculation based on the dimensions selected in the Explore. Finally, I select a time dimension for arrival month to compare flight count by equivalent months across years. The new period_over_period measure type offloads the complexity of period-over-period calculations to Looker, and I can freely explore my data and gather insights.

As of Looker 25.6, we support period_over_period measures for all customers who are using BigQuery, Snowflake and Redshift connections (more to come!) and the new LookML runtime. More details on how to define and use period_over_period measures can be found in our documentation.

The new LookML period_over_period measure puts powerful insights at your fingertips and enables you to spend less time wrestling with your data and more time driving meaningful growth and achieving your business objectives.

Give it a try and let us know what you think by reaching out at looker_pop_feedback@google.com.

18 Likes

this is great - until now we have implemented liquid / lookML versions - So an out of the box solution will be amazing

2 Likes

This will be hugely helpful compared to the old way, excited to try it out.

1 Like

Been waiting for this to come out! This is great as it will simplify the existing code and improve QoL immensely.

1 Like

Love to see this getting implemented after years of requests, can’t wait to try it out

hopefully (or woud be the icing on the cake ) the attributes also accept parameter-values :grinning_face_with_smiling_eyes:

2 Likes

This is great news. It’s good to see some development time being given to fixing obvious gaps, rather than just focusing on delivering new features .

However, I cannot get this to work. When I add a period-over-period measure to my view file, like this:

measure: cost_last_month_previous {
type: period_over_period
based_on: cost
based_on_time: query_month
period: month
kind: previous
}

I get an error message in the Explore:

A LookML model issue occurred.
unknown field type ‘period_over_period’ in field definition

I am a Looker Original customer on release 25.6.17. I don’t know if this is related, but I also cannot see an option to save a Chart Config Editor configuration as a template (which, according to the release notes, was supposed to be available as of Looker 25.6).

2 Likes

BUenos dias !

Esta funcionalidad la van a agregar para base de datos

PostgreSQL 9.5+

?

This is great and super easy to use, but one thing I’d love to be able to use this for is comparing the same day of the year vs. the prior year.

For businesses with significant week seasonality (90% sales on weekdays, 10% sales on weekends, etc) looking at Jan 5th 2025 vs Jan 5th 2024 might not be as useful when they really want to be comparing the 1st Sunday of each year.

2 Likes

Thanks for the feedback, I am looking into this now and will get back to you as soon as I get more information from the team.

We are planning to add additional dialect support for the GA release. The team is investigating the implementation for Postgres, but I can’t give a commitment at this time because the SQL we generate has nuances between dialects. Please stay tuned as we get closer to GA and I’ll have more information on this front.

Thanks for the feedback! We have heard similar things from some of customers who are in the retail/ecommerce space. We are investigating adding more comprehensive custom fiscal calendar support to address the type of scenario you are describing. If you are open to it, I’d love to learn more about your use case: looker_pop_feedback@google.com

1 Like

We don’t see anything on our end so far, but one thing to double check is that you are using the new LookML runtime: https://cloud.google.com/looker/docs/reference/param-manifest-new-lookml-runtime

1 Like

Nice! This is a great solution to a common problem!

Will it work with irregular periods too? I often do prior period, not necessarily set to a fixed calendar segment. A good example is baseball pitchers. They don’t pitch every day. I want to see his performance versus the prior game, not the prior day/week.

1 Like

So grateful to the team for focusing on some core Looker/LookML functionality! Hugely, hugely useful. And +1 that day of week is very important to us, so having the lookback offset by 365D exactly, would be helpful.

4 Likes

It won’t work with irregular periods yet, but its on our backlog and we hope to expand support in the future

1 Like

Thank you Aleksandra - I toggled off the ‘Use Legacy LookML Runtime’ setting in the Admin console, and my period_over_period measures are now visible in the Explore, and working correctly.

It might be worth adding this to the documentation page in the limitations section. It mentions that BigQuery connections should disable the lab feature ‘BI Engine Symmetric Aggregates’, but it doesn’t mention anything about legacy features that will cause breakage.

1 Like

Sorry about that, I’ll make sure it gets added to our documentation under limitations. Glad its working for you now!

Great to see this live :slightly_smiling_face: Cheers!

2 Likes

Thank you for implementing such an excellent feature!
I would like to report an issue I discovered: when trying to apply a filter on the same dimension using datetype: date in the base_on_time dimension, it does not work properly.

My understanding of the Period over Period mechanism is that it aggregates past data in a CTE by grouping it by TIMESTAMP type (e.g., date/month/year), and then uses that to calculate PoP in the main query.
When applying a filter on the base_on_time dimension, the filter is applied twice—once in the past data aggregation CTE and once in the main query. This results in a query error because the WHERE clause types (timestamp and date) differ in the latter.From my understanding, since the period is already filtered in the past data aggregation, the filter in the main query should not be necessary.
Due to this specification, PoP cannot be used on heavy tables that require partitioning, so I would greatly appreciate it if you could address this issue promptly.

4 Likes

Thanks for letting us know about the issue with datatype: date, we are aware of this issue and will be fixing it ASAP!

As far as why there are two filters, let’s say for example that you have a period over period measure that is based on year and you filter on year 2024. We need to extend the filtered period within the context of the CTE to calculate the period over period measure, so in this case the filter is 2023 and 2024 in the CTE so we can tell you what the previous period value is for the year 2024, since it relies on data from 2023.

However, the outermost filter is also necessary because you only want the data returned for 2024.

As far as your comment about not being useful for queries that require partitioning, are you saying this is an issue with the way we are doing multiple filters or just the datatype: date issue is causing the problem?

1 Like