Как получить фрагмент массива в BigQuery Standard SQL? - PullRequest
0 голосов
/ 23 февраля 2019

В BigQuery у меня есть таблица со столбцом path, подобная этой:

ID .     | Path
---------+----------------------------------------
1        | foo/bar/baz
2        | foo/bar/quux/blat

Я хотел бы иметь возможность разделить путь на косой черте (/) и выбрать один илибольше частей пути, соединяя их.

В PostgreSQL это легко:

select array_to_string((regexp_split_to_array(path, '/'))[1:3], '/')

Но BigQuery, похоже, не имеет какой-либо функции смещения диапазона или функции среза массива.

1 Ответ

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

Ниже для BigQuery Standard SQL

#standardSQL
SELECT id, path,
  (
    SELECT STRING_AGG(part, '/' ORDER BY index) 
    FROM UNNEST(SPLIT(path, '/')) part WITH OFFSET index 
    WHERE index BETWEEN 1 AND 3
  ) adjusted_path
FROM `project.dataset.table`  

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

#standardSQL
WITH `project.dataset.table` AS (
  SELECT 1 id, 'foo/bar/baz/foo1/bar1/baz1/' path UNION ALL
  SELECT 2, 'foo/bar/quux/blat/foo2/bar2/quux2/blat2' 
)
SELECT id, path,
  (
    SELECT STRING_AGG(part, '/' ORDER BY index) 
    FROM UNNEST(SPLIT(path, '/')) part WITH OFFSET index 
    WHERE index BETWEEN 1 AND 3
  ) adjusted_path
FROM `project.dataset.table`   

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

Row     id      path                                        adjusted_path    
1       1       foo/bar/baz/foo1/bar1/baz1/                 bar/baz/foo1     
2       2       foo/bar/quux/blat/foo2/bar2/quux2/blat2     bar/quux/blat    

Если по какой-то причине вы хотите, чтобы ваш запрос был «встроенным / похожим» на тот, который вы используете в PostgreSQL (array_to_string ((regexp_split_to_array (path, '/')) [1: 3], '/'))- вы можете ввести SQL UDF (назовем его ARRAY_SLICE), как в примере ниже

#standardSQL
CREATE temp  FUNCTION ARRAY_SLICE(arr ARRAY<STRING>, start INT64, finish INT64) 
RETURNS ARRAY<STRING> AS (
  ARRAY(
    SELECT part FROM UNNEST(arr) part WITH OFFSET index 
    WHERE index BETWEEN start AND finish ORDER BY index
  )
);
SELECT id, path, 
  ARRAY_TO_STRING(ARRAY_SLICE(SPLIT(path, '/'), 1, 3), '/') adjusted_path
FROM `project.dataset.table`  

Очевидно, что если применить к тем же образцам данных - вы получите тот же результат

#standardSQL
CREATE temp  FUNCTION ARRAY_SLICE(arr ARRAY<STRING>, start INT64, finish INT64) 
RETURNS ARRAY<STRING> AS (
  ARRAY(
    SELECT part FROM UNNEST(arr) part WITH OFFSET index 
    WHERE index BETWEEN start AND finish ORDER BY index
  )
);
WITH `project.dataset.table` AS (
  SELECT 1 id, 'foo/bar/baz/foo1/bar1/baz1/' path UNION ALL
  SELECT 2, 'foo/bar/quux/blat/foo2/bar2/quux2/blat2' 
)
SELECT id, path, 
  ARRAY_TO_STRING(ARRAY_SLICE(SPLIT(path, '/'), 1, 3), '/') adjusted_path
FROM `project.dataset.table`   

Row     id      path                                        adjusted_path    
1       1       foo/bar/baz/foo1/bar1/baz1/                 bar/baz/foo1     
2       2       foo/bar/quux/blat/foo2/bar2/quux2/blat2     bar/quux/blat    
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...