2015-03-17 1 views
3

Мне нужно вычислить медианное значение числовой последовательности в Google BigQuery эффективно. Возможно ли такое же?Как эффективно вычислить медианную числовую последовательность в Google BigQuery?

+0

У вас есть низкий уровень. Важно отметить, что вы должны пометить принятые ответы, используя отметку слева от опубликованного ответа ниже голосования. Это увеличит вашу ставку. Посмотрите, как это работает, просматривая эту ссылку: http://meta.stackoverflow.com/questions/5234/how-does-accepting-an-answer-work#5235 – Pentium10

ответ

7

Да, это возможно с PERCENTILE_CONT Функция окна.

Возвращает значения, которые основаны на линейной интерполяции между значениями группы, после того, заказав их в соответствии с ORDER BY пункта.

должна находиться в диапазоне от 0 до 1.

Эта функция окна требует ORDER BY в операторе OVER.

Так пример запроса будет как (макс() есть только для работы по всей группе, но он не используется в качестве математической логики, не должны вас смущать)

SELECT room, 
     max(median) FROM (SELECT room, 
     percentile_cont(0.5) OVER (PARTITION BY room 
            ORDER BY temperature) AS median FROM 
    (SELECT 1 AS room, 
      11 AS temperature), 
    (SELECT 1 AS room, 
      12 AS temperature), 
    (SELECT 1 AS room, 
      14 AS temperature), 
    (SELECT 1 AS room, 
      19 AS temperature), 
    (SELECT 1 AS room, 
      13 AS temperature), 
    (SELECT 2 AS room, 
      20 AS temperature), 
    (SELECT 2 AS room, 
      21 AS temperature), 
    (SELECT 2 AS room, 
      29 AS temperature), 
    (SELECT 3 AS room, 
      30 AS temperature)) GROUP BY room 

Этот возвращает:

+------+-------------+ 
| room | temperature | 
+------+-------------+ 
| 1 |   13 | 
| 2 |   21 | 
| 3 |   30 | 
+------+-------------+ 
+0

Можем ли мы получить более четкий и краткий запрос? Я не мог понять сказанное выше. –

+0

@ManishAgrawal Попробуйте запустить куски, и вы в конце концов поймете, этот запрос прост. Вероятно, для вас новинка - вещь OVER(), которую вам нужно читать дальше, это основа для функций окна. В том случае, если предложение from смущает вас, я попытался реплицировать результаты таблицы, чтобы вы могли скопировать вставку и запустить этот запрос как есть. – Pentium10

5

Альтернативное решение, когда вам не нужно абсолютно точные результаты и приближение отлично - вы можете использовать комбинацию из NTH и квантилей функции агрегации. Преимущество этого метода заключается в том, что он гораздо более масштабируемый, чем функции аналитических окон, но недостатком является то, что он дает приблизительные результаты.

SELECT room, 
     NTH(50, QUANTILES(temperature, 101)) FROM 
    (SELECT 1 AS room, 
      11 AS temperature), 
    (SELECT 1 AS room, 
      12 AS temperature), 
    (SELECT 1 AS room, 
      14 AS temperature), 
    (SELECT 1 AS room, 
      19 AS temperature), 
    (SELECT 1 AS room, 
      13 AS temperature), 
    (SELECT 2 AS room, 
      20 AS temperature), 
    (SELECT 2 AS room, 
      21 AS temperature), 
    (SELECT 2 AS room, 
      29 AS temperature), 
    (SELECT 3 AS room, 
      30 AS temperature) GROUP BY room 

Это возвращает

room temperature 
1 13 
2 21 
3 30 
+0

Я думаю, вам нужно 'NTH (51, QUANTILES (температура, 101))' для медианы, так как 'NTH' - 1. См. Https://cloud.google.com/bigquery/query-reference#quantiles. –

3

Для моих собственных целей памяти, работая запросы с данными такси:

Приблизительные квантилей:

SELECT MONTH(pickup_datetime) month, NTH(51, QUANTILES(tip_amount,101)) median 
FROM [nyc-tlc:green.trips_2015] 
WHERE tip_amount > 0 
GROUP BY 1 
ORDER BY 1 

дает те же результаты, как PERCENTILE_DISC:

SELECT month, FIRST(median) median 
FROM (
    SELECT MONTH(pickup_datetime) month, tip_amount, PERCENTILE_DISC(0.5) OVER(PARTITION BY month ORDER BY tip_amount) median 
    FROM [nyc-tlc:green.trips_2015] 
    WHERE tip_amount > 0 
) 
GROUP BY 1 
ORDER BY 1 

StandardSQL:

#StandardSQL 
SELECT DATE_TRUNC(DATE(pickup_datetime), MONTH) month, APPROX_QUANTILES(tip_amount,1000)[OFFSET(500)] median 
FROM `nyc-tlc.green.trips_2015` 
WHERE tip_amount > 0 
GROUP BY 1 
ORDER BY 1