bigquery: найти следующее условие соответствия строки - PullRequest
0 голосов
/ 22 ноября 2018

Я смотрю на текстовые последовательности в BigQuery и пытаюсь определить завершение слов по ряду строк (разделяя идентификатор).Данные выглядят так:

ID, Text
1, t
1, th
1, the
1, the
1, the c
1, the ca
1, the cat
1, the cat 
1, the cat s
...
1, the cat sat on the mat
2, r
...

Для каждого данного идентификатора и последовательности я пытаюсь найти следующую границу слова.Таким образом, идеальным результатом будет:

ID, Text, Boundary
1, t, the
1, th, the
1, the c, the cat
1, the ca, the cat
1, the cat s, the cat sat 

В приведенном выше примере следующая следующая строка, которая совместно использует идентификатор и заканчивается пробелом, дает следующую (может быть несколько) границу завершения слова.

Ответы [ 2 ]

0 голосов
/ 23 ноября 2018

UDF BigQuery пригодятся в таких ситуациях.Вот рабочее решение:

#standardSQL
/*boundary function*/
create temp function boundaryf (text string, sentence string) as (
  array_to_string(array(
    select q.w from unnest(
      array(select struct(w as w, row_number() over () as i)  from unnest(split(sentence, ' ')) w
      ) 
    ) q
    -- respect the ending space
    where q.i <= array_length(split(text, ' ')) - (length(text) - length(rtrim(text)))
  ), ' ')
);

WITH items AS (
  #--your data. assuming this is already ordered
  SELECT 1 as id, 't' as text UNION ALL
  SELECT 1, 'th' UNION ALL
  SELECT 1, 'the' UNION ALL
  SELECT 1, 'the ' UNION ALL
  SELECT 1, 'the c' UNION ALL
  SELECT 1, 'the ca' UNION ALL
  SELECT 1, 'the cat' UNION ALL
  SELECT 1, 'the cat ' UNION ALL
  SELECT 1, 'the cat s' UNION ALL
  SELECT 1, 'the cat sa' union all
  SELECT 1, 'the cat sat' union all
  SELECT 1, 'the cat sat ' union all
  SELECT 1, 'the cat sat o' union all 
  SELECT 1, 'the cat sat on' union all
  SELECT 1, 'the cat sat on ' union all
  SELECT 1, 'the cat sat on a' union all
  SELECT 1, 'the cat sat on a ' union all
  SELECT 1, 'the cat sat on a m' union all
  SELECT 1, 'the cat sat on a ma' union all
  SELECT 1, 'the cat sat on a mat' union all
  select 2, 'i' union all
  select 2, 'i a' union all
  select 2, 'i am' union all
  select 2, 'i am f' union all
  select 2, 'i am fr' union all
  select 2, 'i am fre' union all
  select 2, 'i am free'
),
sentences as (
  select id, sentences[offset (array_length(sentences)-1)] as sentence from (
    select id, array_agg(text) as sentences 
    from items group by 1
  )
),
control as (
  select i.id, i.text, boundaryf(i.text, s.sentence) as boundary
  from items i
  left join sentences s on s.id  = i.id
)
select * from control
0 голосов
/ 22 ноября 2018

Ниже приведено описание BigQuery Standard SQL

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

#standardSQL
SELECT id, item, boundary
FROM (
  SELECT id, grp, 
    STRING_AGG(IF(boundary, text, ''), '') boundary,
    ARRAY_AGG(IF(NOT boundary, text, NULL) IGNORE NULLS ORDER BY LENGTH(text)) items
  FROM (
    SELECT id, text, 
      LENGTH(text) - LENGTH(REPLACE(text, ' ', '')) - IF(SUBSTR(text, -1) = ' ', 1, 0) grp,
      SUBSTR(text, -1) = ' ' boundary
    FROM `project.dataset.table`
  )
  GROUP BY id, grp
), UNNEST(items) item WITH OFFSET pos
WHERE RTRIM(item) != RTRIM(boundary)

если применить к фиктивным данным в вашем вопросе, как показано ниже

#standardSQL
WITH `project.dataset.table` AS (
  SELECT 1 id, 't' text UNION ALL
  SELECT 1, 'th' UNION ALL
  SELECT 1, 'the' UNION ALL
  SELECT 1, 'the ' UNION ALL
  SELECT 1, 'the c' UNION ALL
  SELECT 1, 'the ca' UNION ALL
  SELECT 1, 'the cat' UNION ALL
  SELECT 1, 'the cat ' UNION ALL
  SELECT 1, 'the cat s' UNION ALL
  SELECT 1, 'the cat sat ' 
)
SELECT id, item, boundary
FROM (
  SELECT id, grp, 
    STRING_AGG(IF(boundary, text, ''), '') boundary,
    ARRAY_AGG(IF(NOT boundary, text, NULL) IGNORE NULLS ORDER BY LENGTH(text)) items
  FROM (
    SELECT id, text, 
      LENGTH(text) - LENGTH(REPLACE(text, ' ', '')) - IF(SUBSTR(text, -1) = ' ', 1, 0) grp,
      SUBSTR(text, -1) = ' ' boundary
    FROM `project.dataset.table`
  )
  GROUP BY id, grp
), UNNEST(items) item WITH OFFSET pos
WHERE RTRIM(item) != RTRIM(boundary)
ORDER BY id, grp, pos   

результат равен

Row     id      item        boundary     
1       1       t           the  
2       1       th          the  
3       1       the c       the cat  
4       1       the ca      the cat  
5       1       the cat s   the cat sat  
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...