# Calculate period-to-period change in SQL

## Method 1

This assumes that a single row exist for each user and each period (by day, in our example). In this case, the calculation can be made in one step with `LAG()`:

``````-- One step: count distinct users and use LAG()
SELECT
date,
COUNT(DISTINCT user_id) AS users,
LAG(COUNT(DISTINCT user_id)) OVER (ORDER BY date) AS prev_users,
COUNT(DISTINCT user_id) / LAG(COUNT(DISTINCT user_id)) OVER (ORDER BY date) -1 AS change
FROM `training.ga_users`
GROUP BY 1
ORDER BY date
LIMIT 10
``````
``````| date       | users | prev_users | change    |
|------------|-------|------------|-----------|
| 2017-01-01 | 134   | NaN        | NaN       |
| 2017-01-02 | 138   | 134.0      | 0.029851  |
| 2017-01-03 | 207   | 138.0      | 0.500000  |
| 2017-01-04 | 220   | 207.0      | 0.062802  |
| 2017-01-05 | 184   | 220.0      | -0.163636 |
| 2017-01-06 | 191   | 184.0      | 0.038043  |
| 2017-01-07 | 131   | 191.0      | -0.314136 |
| 2017-01-08 | 144   | 131.0      | 0.099237  |
| 2017-01-09 | 200   | 144.0      | 0.388889  |
| 2017-01-10 | 214   | 200.0      | 0.070000  |
``````

## Method 2

If there is not a single row for each period, then a self join should be used:

1. Group by period and count users
2. Self join on offset period, and calculate change over previous period
``````-- Step 1: count users at period level
WITH sub1 AS (
SELECT
date,
COUNT(*) AS users
FROM `training.ga_users`
GROUP BY 1
)

-- Step 2: self-join and calculate change over previous period
SELECT
curr.date,
curr.users AS users,
prev.users AS prev_users,
curr.users/prev.users-1 AS change
FROM sub1 AS curr
LEFT JOIN sub1 AS prev
ON prev.date = DATE_ADD(curr.date, INTERVAL -1 DAY)
ORDER BY date
LIMIT 10
``````
``````| date       | users | prev_users | change    |
|------------|-------|------------|-----------|
| 2017-01-01 | 134   | NaN        | NaN       |
| 2017-01-02 | 138   | 134.0      | 0.029851  |
| 2017-01-03 | 207   | 138.0      | 0.500000  |
| 2017-01-04 | 220   | 207.0      | 0.062802  |
| 2017-01-05 | 184   | 220.0      | -0.163636 |
| 2017-01-06 | 191   | 184.0      | 0.038043  |
| 2017-01-07 | 131   | 191.0      | -0.314136 |
| 2017-01-08 | 144   | 131.0      | 0.099237  |
| 2017-01-09 | 200   | 144.0      | 0.388889  |
| 2017-01-10 | 214   | 200.0      | 0.070000  |
``````