Ниже для BigQuery Standard SQL
#standardSQL
CREATE TEMP FUNCTION Median(arr ARRAY<INT64>) AS (
IF(MOD(ARRAY_LENGTH(arr), 2) = 1, arr[OFFSET(DIV(ARRAY_LENGTH(arr), 2))],
(arr[OFFSET(DIV(ARRAY_LENGTH(arr), 2) - 1)] + arr[OFFSET(DIV(ARRAY_LENGTH(arr), 2))]) / 2)
);
SELECT Median(ARRAY_AGG(score ORDER BY score)) Median
FROM `project.dataset.document`
WHERE DATE(dt) >= DATE_SUB(CURRENT_DATE(), INTERVAL 30 DAY)
Вы можете общаться, поиграть с выше, используя пример данных из вашего вопроса, как в примере ниже
#standardSQL
CREATE TEMP FUNCTION Median(arr ARRAY<INT64>) AS (
IF(MOD(ARRAY_LENGTH(arr), 2) = 1, arr[OFFSET(DIV(ARRAY_LENGTH(arr), 2))],
(arr[OFFSET(DIV(ARRAY_LENGTH(arr), 2) - 1)] + arr[OFFSET(DIV(ARRAY_LENGTH(arr), 2))]) / 2)
);
WITH `project.dataset.document` AS (
SELECT 'A' dId, 100 score, DATETIME '2019-03-08 16:17:34.043' dt UNION ALL
SELECT 'B', 80, '2019-02-15 16:17:34.043' UNION ALL
SELECT 'C', 70, '2019-03-08 16:17:34.043'
)
SELECT Median(ARRAY_AGG(score ORDER BY score)) Median
FROM `project.dataset.document`
WHERE DATE(dt) >= DATE_SUB(CURRENT_DATE(), INTERVAL 30 DAY)
с результатом
Row Median
1 85.0
Обратите внимание, что вы можете использовать CREATE TEMP FUNCTION Median(arr ANY TYPE) AS (...
, чтобы сделать его более универсальным и принять любой тип последовательности
Обновление
Ниже приведен пример работы с NUMERIC
#standardSQL
CREATE TEMP FUNCTION Median(arr ANY TYPE) AS (
IF(MOD(ARRAY_LENGTH(arr), 2) = 1, arr[OFFSET(DIV(ARRAY_LENGTH(arr), 2))],
(arr[OFFSET(DIV(ARRAY_LENGTH(arr), 2) - 1)] + arr[OFFSET(DIV(ARRAY_LENGTH(arr), 2))]) / 2)
);
WITH `project.dataset.document` AS (
SELECT 'A' dId, CAST(100.0 AS numeric) score, DATETIME '2019-03-08 16:17:34.043' datetime UNION ALL
SELECT 'B', 80.5, '2019-02-15 16:17:34.043' UNION ALL
SELECT 'C', 70.1, '2019-03-08 16:17:34.043'
)
SELECT Median(ARRAY_AGG(CAST(score AS FLOAT64) ORDER BY score)) Median
FROM `project.dataset.document`
WHERE DATE(datetime) >= DATE_SUB(CURRENT_DATE(), INTERVAL 30 DAY)
Обновление
Хорошо. Обнаружена причина внутренней ошибки - из-за упорядочения по числовому значению
Итак, окончательная версия:
#standardSQL
CREATE TEMP FUNCTION Median(arr ANY TYPE) AS (
IF(MOD(ARRAY_LENGTH(arr), 2) = 1, arr[OFFSET(DIV(ARRAY_LENGTH(arr), 2))],
(arr[OFFSET(DIV(ARRAY_LENGTH(arr), 2) - 1)] + arr[OFFSET(DIV(ARRAY_LENGTH(arr), 2))]) / 2)
);
WITH `project.dataset.document` AS (
SELECT 'A' dId, CAST(100.0 AS numeric) score, DATETIME '2019-03-08 16:17:34.043' datetime UNION ALL
SELECT 'B', 80.5, '2019-02-15 16:17:34.043' UNION ALL
SELECT 'C', 70.1, '2019-03-08 16:17:34.043'
)
SELECT Median(ARRAY_AGG(score ORDER BY CAST(score AS FLOAT64))) Median
FROM `project.dataset.document`
WHERE DATE(datetime) >= DATE_SUB(CURRENT_DATE(), INTERVAL 30 DAY)