Есть ли расчеты в большом запросе в пределах строки и медианы - возможно ли это? - PullRequest
0 голосов
/ 22 февраля 2019

Моя проблема в получении необработанного набора сенсорных данных, которые требуют некоторой обработки, прежде чем я смогу их использовать.загрузка данных на клиент и выполнение обработки происходит довольно медленно, поэтому я ищу возможность выгрузить эту логику в bigquery.

Представьте, что у меня есть несколько констант для набора датчиков.Они могут меняться, но у меня они есть, когда я хочу выполнить запрос

A: 1, B: 2, C: 3, D: 2, E: 1, F: 2

Датчики подключены, я знаю, какие датчики подключены друг к другу.Это имеет значение ниже.

A: BC
D: EF

Это таблица с измерениями на отметку времени на датчик.Представьте себе тысячи строк.

TS    A  |  B  |  C  |  D  |  E  |  F  
01    10 |  20 |  10 |  10 |  15 | 10
02    11 |  10 |  20 |  20 |  10 | 10
03    12 |  20 |  10 |  10 |  12 | 11
04    13 |  10 |  10 |  20 |  15 | 15
05    11 |  20 |  10 |  15 |  14 | 14
06    10 |  20 |  10 |  10 |  15 | 12

Я хочу запросить от 01 до 06 (в действительности это может быть снова 1000 строк).Я не хочу, чтобы он возвращал эти необработанные данные, но он должен выполнить некоторые вычисления:

Во-первых, для каждой строки мне нужно отвлечь константы, поэтому строка 01 будет выглядеть следующим образом:

01    9 |  18 |  17 |  8 |  14 | 8

Затем BC нужно отвести A, а EF - D:

01    9 |   9 |   8 |  8 |   6 | 0

Последний шаг, когда у меня есть все строки, я хочу вернуть строки, где у каждого датчика есть медианазначение исходящих X строк для этого датчика.Так что

    TS    A  |  B  | 
    01    10 |  1  | 
    02    11 |  2  |  
    03    12 |  2  |  
    04    13 |  1  |  
    05    11 |  2  | 
    06    10 |  3  |  
    07    10 |  4  | 
    08    11 |  2  |  
    09    12 |  2  |  
    10    13 |  10 |  
    11    11 |  20 | 
    12    10 |  20 |  

возвращает (для X 4)

    TS    A  |  B  | 
   //first 3 needed for median for 4th value
    04    11.5 |  etc  |   //median 10, 11, 12, 13
    05    11.5 |  etc  |   //median 11, 12, 13, 11
    06    11.5 |  etc  |   //median 12, 13, 11, 10
    07    etc |  etc | 
    08    etc |  etc |  
    09    etc |  etc |  
    10    etc |  etc |  
    11    etc |  etc | 
    12    etc |  etc |  

Получение данных на моем сервере и выполнение расчета очень медленно, мне действительно интересно, сможем ли мы получить эти суммыданных в bigQuery, так что я могу получить быстрый расчетный набор с моими собственными настройками выбора!

Я делаю это в Node.js ... но в BigQuery SQL .. я потерян.

1 Ответ

0 голосов
/ 23 февраля 2019

Ниже для стандартного SQL BigQuery

Если вы ищете значения AVG - это будет так же просто, как показано ниже

#standardSQL
WITH constants AS (
  SELECT 1 val_a, 2 val_b, 3 val_c, 2 val_d, 1 val_e, 2 val_f
), temp AS (
  SELECT ts,
    a - val_a AS a, 
    b - val_b - a + val_a AS b,
    c - val_c - a + val_a AS c,
    d - val_d AS d,
    e - val_e - d + val_d  AS e,
    f - val_f - d + val_d AS f
  FROM `project.dataset.measurements`, constants
)
SELECT ts, 
  AVG(a) OVER(ORDER BY ts ROWS BETWEEN 4 PRECEDING AND 1 PRECEDING) a,  
  AVG(b) OVER(ORDER BY ts ROWS BETWEEN 4 PRECEDING AND 1 PRECEDING) b,  
  AVG(c) OVER(ORDER BY ts ROWS BETWEEN 4 PRECEDING AND 1 PRECEDING) c,  
  AVG(d) OVER(ORDER BY ts ROWS BETWEEN 4 PRECEDING AND 1 PRECEDING) d,  
  AVG(e) OVER(ORDER BY ts ROWS BETWEEN 4 PRECEDING AND 1 PRECEDING) e,  
  AVG(f) OVER(ORDER BY ts ROWS BETWEEN 4 PRECEDING AND 1 PRECEDING) f  
FROM temp

Для MEDIAN вам нужно добавить немного дополнений- как в примере ниже

#standardSQL
WITH constants AS (
  SELECT 1 val_a, 2 val_b, 3 val_c, 2 val_d, 1 val_e, 2 val_f
), temp AS (
  SELECT ts,
    a - val_a AS a, 
    b - val_b - a + val_a AS b,
    c - val_c - a + val_a AS c,
    d - val_d AS d,
    e - val_e - d + val_d  AS e,
    f - val_f - d + val_d AS f
  FROM `project.dataset.measurements`, constants
)
SELECT ts,
  (SELECT PERCENTILE_CONT(a, 0.5) OVER() FROM UNNEST(a) a LIMIT 1) a,
  (SELECT PERCENTILE_CONT(b, 0.5) OVER() FROM UNNEST(b) b LIMIT 1) b,
  (SELECT PERCENTILE_CONT(c, 0.5) OVER() FROM UNNEST(c) c LIMIT 1) c,
  (SELECT PERCENTILE_CONT(d, 0.5) OVER() FROM UNNEST(d) d LIMIT 1) d,
  (SELECT PERCENTILE_CONT(e, 0.5) OVER() FROM UNNEST(e) e LIMIT 1) e,
  (SELECT PERCENTILE_CONT(f, 0.5) OVER() FROM UNNEST(f) f LIMIT 1) f
FROM (
  SELECT ts, 
    ARRAY_AGG(a) OVER(ORDER BY ts ROWS BETWEEN 4 PRECEDING AND 1 PRECEDING) a,  
    ARRAY_AGG(b) OVER(ORDER BY ts ROWS BETWEEN 4 PRECEDING AND 1 PRECEDING) b,  
    ARRAY_AGG(c) OVER(ORDER BY ts ROWS BETWEEN 4 PRECEDING AND 1 PRECEDING) c,  
    ARRAY_AGG(d) OVER(ORDER BY ts ROWS BETWEEN 4 PRECEDING AND 1 PRECEDING) d,  
    ARRAY_AGG(e) OVER(ORDER BY ts ROWS BETWEEN 4 PRECEDING AND 1 PRECEDING) e,  
    ARRAY_AGG(f) OVER(ORDER BY ts ROWS BETWEEN 4 PRECEDING AND 1 PRECEDING) f  
  FROM temp
)

Вы можете протестировать, поиграть с выше, используя примеры данных из вашего вопроса, как в примере ниже

#standardSQL
WITH `project.dataset.measurements` AS (
  SELECT 01 ts, 10 a, 20 b, 20 c, 10 d, 15 e, 10 f UNION ALL
  SELECT 02, 11, 10, 20, 20, 10, 10 UNION ALL
  SELECT 03, 12, 20, 10, 10, 12, 11 UNION ALL
  SELECT 04, 13, 10, 10, 20, 15, 15 UNION ALL
  SELECT 05, 11, 20, 10, 15, 14, 14 UNION ALL
  SELECT 06, 10, 20, 10, 10, 15, 12 
), constants AS (
  SELECT 1 val_a, 2 val_b, 3 val_c, 2 val_d, 1 val_e, 2 val_f
), temp AS (
  SELECT ts,
    a - val_a AS a, 
    b - val_b - a + val_a AS b,
    c - val_c - a + val_a AS c,
    d - val_d AS d,
    e - val_e - d + val_d  AS e,
    f - val_f - d + val_d AS f
  FROM `project.dataset.measurements`, constants
)
SELECT ts,
  (SELECT PERCENTILE_CONT(a, 0.5) OVER() FROM UNNEST(a) a LIMIT 1) a,
  (SELECT PERCENTILE_CONT(b, 0.5) OVER() FROM UNNEST(b) b LIMIT 1) b,
  (SELECT PERCENTILE_CONT(c, 0.5) OVER() FROM UNNEST(c) c LIMIT 1) c,
  (SELECT PERCENTILE_CONT(d, 0.5) OVER() FROM UNNEST(d) d LIMIT 1) d,
  (SELECT PERCENTILE_CONT(e, 0.5) OVER() FROM UNNEST(e) e LIMIT 1) e,
  (SELECT PERCENTILE_CONT(f, 0.5) OVER() FROM UNNEST(f) f LIMIT 1) f
FROM (
  SELECT ts, 
    ARRAY_AGG(a) OVER(ORDER BY ts ROWS BETWEEN 4 PRECEDING AND 1 PRECEDING) a,  
    ARRAY_AGG(b) OVER(ORDER BY ts ROWS BETWEEN 4 PRECEDING AND 1 PRECEDING) b,  
    ARRAY_AGG(c) OVER(ORDER BY ts ROWS BETWEEN 4 PRECEDING AND 1 PRECEDING) c,  
    ARRAY_AGG(d) OVER(ORDER BY ts ROWS BETWEEN 4 PRECEDING AND 1 PRECEDING) d,  
    ARRAY_AGG(e) OVER(ORDER BY ts ROWS BETWEEN 4 PRECEDING AND 1 PRECEDING) e,  
    ARRAY_AGG(f) OVER(ORDER BY ts ROWS BETWEEN 4 PRECEDING AND 1 PRECEDING) f  
  FROM temp
)
-- ORDER BY ts   

с результатом

Row ts  a       b       c       d       e       f    
1   1   null    null    null    null    null    null     
2   2   9.0     9.0     8.0     8.0     6.0     0.0  
3   3   9.5     3.5     7.5     13.0    -1.5    -5.0     
4   4   10.0    7.0     7.0     8.0     3.0     0.0  
5   5   10.5    2.5     1.5     13.0    -0.5    -2.5     
6   6   10.5    2.5     -3.5    15.5    -2.0    -3.0       
...