将字符串与特定文本匹配的正则表达式不在 BigQuery 中的文本之间

Regex that matches strings with specific text not between text in BigQuery

我有以下字符串:

step_1->step_2->step_3
step_1->step_3
step_1->step_2->step_1->step_3
step_1->step_2->step_1->step_2->step_3

我想做的是捕获 step_1 和步骤 3 之间没有 step_2 的那些。

结果应该是这样的:

string                                   result
step_1->step_2->step_3                    false
step_1->step_3                             true
step_1->step_2->step_1->step_3             true
step_1->step_2->step_1->step_2->step_3    false

我曾尝试使用负前瞻,但我发现 BigQuery 不支持它。有什么想法吗?

你本质上是在寻找模式何时不存在。以下正则表达式将支持嵌入在 case 语句中的内容。这不支持您在单个字符串中同时具有两个条件的情况,但是您在示例数据中列出的情况并非如此。

尝试以下操作:

with sample_data as (
    select 'step_1->step_2->step_3' as string union all
    select 'step_1->step_3' union all
    select 'step_1->step_2->step_1->step_3'  union all
    select 'step_1->step_2->step_1->step_2->step_3' union all 
    select 'step_1->step_2->step_1->step_2->step_2->step_3' union all 
    select 'step_1->step_2->step_1->step_2->step_2' 
)

select 
    string,
    -- CASE WHEN regexp_extract(string, r'step_1->(\w+)->step_3') IS NULL THEN TRUE
    CASE WHEN regexp_extract(string, r'1(->step_2)+->step_3') IS NULL THEN TRUE
    ELSE FALSE END as result
from sample_data 

这导致:

我相信@Daniel_Zagales 的回答正是您所期待的。然而,这里有一个更广泛的解决方案,可能对您的 usecase:it 感兴趣,包括使用数组

 WITH sample AS (
  SELECT 'step_1->step_2->step_3' AS path
  UNION ALL SELECT 'step_1->step_3'
  UNION ALL SELECT 'step_1->step_2->step_1->step_3'
  UNION ALL SELECT 'step_1->step_2->step_1->step_2->step_3'
),
  temp AS (
  SELECT
    path,
    SPLIT(REGEXP_REPLACE(path,'step_', ''), '->') AS sequences
  FROM
    sample)
SELECT
  path,
  position,
  flattened AS current_step,
  LAG(flattened) OVER (PARTITION BY path ORDER BY OFFSET ) AS previous_step,
  LEAD(flattened) OVER (PARTITION BY path ORDER BY OFFSET ) AS following_step
FROM
  temp,
  temp.sequences AS flattened
WITH
OFFSET AS position
 

本次查询returns以下table

概念是获取步数数组(拆分“->”并擦除 'step_')并保留 OFFSET(作为 UNNESTing 数组至关重要不保证保持数组的顺序)。

得到的table包含了该路径的每条路径和步骤,前一步和后一步。因此,如果连续的步骤相差 1,则很容易测试。

(例如SELECT * FROM <previous> WHERE ABS(current_step-previous_step) != 1

(需要 CASTINT

同时考虑以下选项

select string, 
  not regexp_contains(string, r'step_1->(step_2->)+step_3\b') as result
from your_table