Функция навигации BigQuery - фильтрация внутри PERCENTILE_CONT - PullRequest
0 голосов
/ 07 мая 2020
WITH transactions AS (
  SELECT
    "cust1" AS customer_id,
    5 AS amount,
    DATE "2020-01-01" AS date
  UNION ALL SELECT "cust1", 1000, DATE "2020-03-05",
  UNION ALL SELECT "cust1", 10, DATE "2020-04-01",
  UNION ALL SELECT "cust1", 18, DATE "2020-04-03",
  UNION ALL SELECT "cust1", 48, DATE "2020-04-05",

  UNION ALL SELECT "cust2", 63, DATE "2020-01-05",
  UNION ALL SELECT "cust2", 3, DATE "2020-03-01",
  UNION ALL SELECT "cust2", 27, DATE "2020-03-05"
)

SELECT
  customer_id,
  amount,
  date,
  PERCENTILE_CONT(amount, 0.5) OVER (
    PARTITION BY
      customer_id
    -- the following ORDER BY and window frame clause are not proper syntax
    -- but this is essentially what I would like to get at
    ORDER BY
      date DESC
    ROWS BETWEEN 30 DAYS PRECEDING AND CURRENT ROW
  ) AS median_last_month
FROM transactions
WHERE
  customer_id = "cust1"

Работа со стандартом BigQuery SQL здесь. Я хочу вычислить медиану строки (см. Пример запроса). Кроме того, я хочу, чтобы медиана рассчитывалась только для транзакций, которые произошли в прошлом месяце относительно текущей строки.

Мои ожидаемые результаты будут

"cust1", 5, "2020-01-01", 5
"cust1", 1000, "2020-03-05", 1000
"cust1", 10, "2020-04-01", 505
"cust1", 18, "2020-04-03", 18
"cust1", 48, "2020-04-05", 33

Я вижу, что для нескольких других Функции навигации в BigQuery вы можете указать «предложение оконного фрейма», но не с помощью PERCENTILE_CONT. Есть предложения?

Ответы [ 2 ]

1 голос
/ 07 мая 2020

PERCENTILE_CONT() не делает то, что вы хотите - увы. Это не функция агрегации и не позволяет использовать оконный фрейм.

Один из методов довольно грубый - самосоединение: укажите «месяц». Поскольку это может меняться в зависимости от сегодняшнего дня, я не могу придумать простой способ справиться с этим.

1 голос
/ 07 мая 2020

Поскольку функция percentile_cont не принимает определение окна, вы можете использовать array_agg для создания массива в пределах определенного диапазона, а затем вы можете вычислить медиану.

Чтобы определить 30-дневное окно, я преобразовал дату to Unix timestamp в секундах и снова использовал окно диапазона с использованием секунд.

WITH transactions AS (
  SELECT
    "cust1" AS customer_id,
    5 AS amount,
    DATE "2020-01-01" AS date
  UNION ALL SELECT "cust1", 1000, DATE "2020-03-05",
  UNION ALL SELECT "cust1", 10, DATE "2020-04-01",
  UNION ALL SELECT "cust1", 18, DATE "2020-04-03",
  UNION ALL SELECT "cust1", 48, DATE "2020-04-05",

  UNION ALL SELECT "cust2", 63, DATE "2020-01-05",
  UNION ALL SELECT "cust2", 3, DATE "2020-03-01",
  UNION ALL SELECT "cust2", 27, DATE "2020-03-05"
),
transactions_amount_agg AS
(
  SELECT
    customer_id,
    amount,
    date,
    ARRAY_AGG(amount) OVER (
      PARTITION BY
        customer_id
      ORDER BY
        UNIX_SECONDS(TIMESTAMP(date))
      RANGE BETWEEN 2592000 PRECEDING AND CURRENT ROW -- 2592000 = 30 * 24 * 60 * 60 
    ) AS last_month_values
  FROM transactions
)
select *, 
  (
    SELECT PERCENTILE_CONT(val, 0.5) OVER ()
    FROM UNNEST(last_month_values) as val
    LIMIT 1
  ) AS median_last_month
from transactions_amount_agg
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...