Function table / Table calculations / Percent change from previous period

Percent change from previous period, from Tableau to SQL

Measures revenue change relative to the absolute previous period revenue. Below, 8 sample rows go through the calculation and through the SQL, and both return the same numbers.

Calculated field

(SUM([Revenue]) - LOOKUP(SUM([Revenue]), -1)) / ABS(LOOKUP(SUM([Revenue]), -1))

Compute using: addressing Period; partitioning Region

Sample data

RegionPeriodRevenueCost
Harbor112070
Harbor2180100
Harbor3180120
Harbor4240140
Upland19050
Upland2150110
Upland3null90
Upland4330190

The same calculation as SQL

SELECT CAST((("Revenue" - lag("Revenue",1) OVER (PARTITION BY "Region" ORDER BY "Period")) / nullif(abs(lag("Revenue",1) OVER (PARTITION BY "Region" ORDER BY "Period")),0)) AS DOUBLE) AS result FROM input ORDER BY "Region", "Period"

Runs the example above.

Result

RegionPeriodRevenueCostresult
Harbor112070null
Harbor21801000.5
Harbor31801200
Harbor42401400.333333
Upland19050null
Upland21501100.666667
Upland3null90null
Upland4330190null

Same rows from the calculation and from the SQL in DuckDB.

Where a naive translation goes wrong

  • An unpartitioned SQL window mixes independent regional calculation sequences.

    Naive SQL

    SELECT CAST((("Revenue" - lag("Revenue",1) OVER ( ORDER BY "Period")) / nullif(abs(lag("Revenue",1) OVER ( ORDER BY "Period")),0)) AS DOUBLE) AS result FROM input ORDER BY "Region", "Period"
    RegionPeriodRevenueCostresult
    Harbor112070null
    Harbor21801001
    Harbor31801200.2
    Harbor4240140null
    Upland19050-0.25
    Upland2150110-0.166667
    Upland3null90null
    Upland43301900.375

    Matches the calculation

    SELECT CAST((("Revenue" - lag("Revenue",1) OVER (PARTITION BY "Region" ORDER BY "Period")) / nullif(abs(lag("Revenue",1) OVER (PARTITION BY "Region" ORDER BY "Period")),0)) AS DOUBLE) AS result FROM input ORDER BY "Region", "Period"
    RegionPeriodRevenueCostresult
    Harbor112070null
    Harbor21801000.5
    Harbor31801200
    Harbor42401400.333333
    Upland19050null
    Upland21501100.666667
    Upland3null90null
    Upland4330190null

Signature

(SUM([Revenue]) - LOOKUP(SUM([Revenue]), -1)) / ABS(LOOKUP(SUM([Revenue]), -1))