Ниже для BigQuery Standard SQL
#standardSQL
SELECT Person_ID,
DATE_DIFF(Middle, Initial, DAY) AS Middle_Minus_initial,
DATE_DIFF(`End`, Initial, DAY) AS End_Minus_initial,
DATE_DIFF(Close, Initial, DAY) AS Close_Minus_initial
FROM (
SELECT Person_ID,
PARSE_DATE('%d/%m/%Y', MAX(IF(Action = 'Initial', `Date`, NULL))) AS Initial,
PARSE_DATE('%d/%m/%Y', MAX(IF(Action = 'Middle', `Date`, NULL))) AS Middle,
PARSE_DATE('%d/%m/%Y', MAX(IF(Action = 'End', `Date`, NULL))) AS `End`,
PARSE_DATE('%d/%m/%Y', MAX(IF(Action = 'Close', `Date`, NULL))) AS Close
FROM `project.dataset.table`
GROUP BY Person_ID
)
Вы можете протестировать, поиграть с выше, используя примеры данных из вашего вопроса, как в примере ниже
#standardSQL
WITH `project.dataset.table` AS (
SELECT 100 Person_ID, 'Initial' Action, '22/12/2018' `Date` UNION ALL
SELECT 100, 'Middle', '23/12/2018' UNION ALL
SELECT 100, 'End', '29/12/2018' UNION ALL
SELECT 100, 'Close', '31/12/2018' UNION ALL
SELECT 150, 'Initial', '02/01/2019' UNION ALL
SELECT 150, 'Middle', '04/01/2019' UNION ALL
SELECT 150, 'End', '07/01/2019' UNION ALL
SELECT 150, 'Close', '10/01/2019'
)
SELECT Person_ID,
DATE_DIFF(Middle, Initial, DAY) AS Middle_Minus_initial,
DATE_DIFF(`End`, Initial, DAY) AS End_Minus_initial,
DATE_DIFF(Close, Initial, DAY) AS Close_Minus_initial
FROM (
SELECT Person_ID,
PARSE_DATE('%d/%m/%Y', MAX(IF(Action = 'Initial', `Date`, NULL))) AS Initial,
PARSE_DATE('%d/%m/%Y', MAX(IF(Action = 'Middle', `Date`, NULL))) AS Middle,
PARSE_DATE('%d/%m/%Y', MAX(IF(Action = 'End', `Date`, NULL))) AS `End`,
PARSE_DATE('%d/%m/%Y', MAX(IF(Action = 'Close', `Date`, NULL))) AS Close
FROM `project.dataset.table`
GROUP BY Person_ID
)
-- ORDER BY Person_ID
с результатом
Row Person_ID Middle_Minus_initial End_Minus_initial Close_Minus_initial
1 100 1 7 9
2 150 2 5 8