Ниже для BigQuery Standard SQL и используйте только один GROUP BY для получения resurface_rate per year
Я не уверен, имеет ли это много практического значения (так как он использует относительно дорогие функции регулярного выраженияи с большим количеством сайтов могут иметь масштабную проблему), но как концептуальная версия интересна, я думаю
#standardSQL
CREATE TEMP FUNCTION extract_year(date ANY TYPE) AS (
SUBSTR(date, 1, 4) -- if stored as YYYYMMDD as string
-- EXTRACT(YEAR FROM date) -- if stored as DATE type
); -- just to abstact year extraction from user's data as it is not that important but really depends on how exactly it is stored
SELECT extract_year(date) year,
1 - ARRAY_LENGTH(REGEXP_EXTRACT_ALL(REGEXP_REPLACE(
CONCAT(STRING_AGG(site ORDER BY site), ','),
STRING_AGG(DISTINCT CONCAT('(',site,',){2,}'), '|'),
''
), ',')) / COUNT(DISTINCT site) AS resurface_rate
FROM `project.dataset.table`
GROUP BY year
Если применить к образцу данных из вашего вопроса - результат
Row year resurface_rate
1 2019 0.6666666666666667
Скорее всего, можно еще «упростить» - но просто хотел поделиться этой неортодоксальной версией