Match_Recognize в Snowflake не возвращает то, что, по моему мнению, должно

Я уверен, что не понимаю этого, но это определяется как

ШАБЛОН: указание шаблона для соответствия ШАБЛОН () Шаблон определяет допустимую последовательность строк, которая представляет совпадение. Шаблон определяется как регулярное выражение (regex) и состоит из символов, операторов и квантификаторов.

Пример был:

Например, предположим, что символ S1 определен как stock_price <55, а символ S2 определен как цена акции> 55. Следующий шаблон определяет последовательность строк, в которых цена акции увеличилась с менее 55 до более 55:

ШАБЛОН (S1 S2)

Так что если я сделаю

      create or replace table names (id int, name varchar (500), groupid int); 

insert into names
           select 1, 'andrew', 1
           union
           select 2, 'andrew2', 1
           union
           select 3, '3andrew', 1

А потом я делаю

      select * from names
match_recognize(
partition by groupid order by id
measures
  classifier() as "classifier"
  all rows per match  
pattern (test test2)  
define test as startswith(name, 'and'),
  test2 as endswith(name, 'rew') 
 ) t
;        

Почему я не получаю «Эндрю» в качестве рекордного дохода? Если я использую какой-либо тест в шаблоне, он это показывает. Когда я вставляю оба, этого не происходит. Вместо этого он показывает 3andrew и andrew2 как результат записи, что для меня неожиданно, потому что этот пример заставил меня поверить, что он работает как AND. Любая помощь приветствуется.

2 ответа

Шаблон (test test2)что означает найти ровно одну строку, начинающуюся с And за которым следует ровно тот , у которого есть rewсуффикс. Окно рисунка имеет размер 2.

Строки обрабатываются следующим образом:

      1 andrew
2 andrew2
3 3andrew

Пройдите 1:

      1 andrew
2 andrew2  -- fails it is not test2

Шаг 2 (на этом этапе строка 1 была пропущена):

      2 andrew2   -- test  pass
3 3andrew   -- test2 pass

Верните строки 2 и 3 и снова запустите процесс поиска (если это еще строки для обработки).

Если вы хотите произвольное количество тестов, то шаблон должен быть (test+ test2) - (размер окна не менее 2).

Если вы хотите, чтобы элемент был одним из двух, тогда шаблон должен быть (test|test2) - (размер окна 1).


Рекомендуемая литература: match_recognize - Регулярные выражения поверх строк

так что твой образец pattern (test test2) Насколько я понимаю, это сказать, найти строку, где проходит, и последнюю строку, где проходит.

MATCH_RECOGNIZE говорит об операторе (пробел), который у вас есть между двумя вашими правилами:

Конкатенация. Указывает, что символ или операция должны следовать за другим. Например, S1 S2 означает, что условие, определенное для S2, должно наступить после условия, определенного для S1.

Но я подозреваю, что ваш вопрос в том, почему идентификатор строки 1 не совпадает с test а затем совпадение строки 3 на test2.. и я считаю, что это AFTER MATCH SKIP по умолчанию PAST LAST ROWкоторые находят тест на совпадение строк 1 и 2, поэтому он начинается после последнего, поэтому вы получаете только одно совпадение. Не то чтобы я мог использовать этот раздел, чтобы отключить такое поведение.

Если немного изменить входные данные:

      WITH names(id, name, groupid) as (
    SELECT * FROM VALUES
        (10, 'andrew', 1),
        (20, '2andrew', 1),
        (30, 'andrew3', 1),
        (40, 'simeon', 1),
        (50, '4andrew', 1)
) 

это дает:

      ID  NAME    GROUPID classifier
10  andrew  1   TEST
20  2andrew 1   TEST2

Таким образом, строка 10 может работать, но кажется, что в ваших данных 2 привязки ближе к 3, но в моих данных 30 не соответствует 50. Также следует отметить, что у вас нет предложения order by в вашем совпадении, что означает, что вы можете получить недетерминированный полученные результаты. Если вы не пересортировали свои данные в другом месте ..

таким образом измените добавление partition а также order предложение означает, что оба Эндрю теперь запускаются:

      WITH names(id, name, groupid) as (
    SELECT * FROM VALUES
        (10, 'andrew', 1),
        (11, 'simeon', 2),
        (20, '2andrew', 1),
        (30, 'andrew3', 1),
        (60, 'simeon', 1),
        (50, '4andrew', 1)
)           
select * 
from names
match_recognize(
  partition by groupid 
  order by id
  measures
    classifier() as "classifier"
    all rows per match  

  pattern (test test2)  
  define test as startswith(name, 'and'),
    test2 as endswith(name, 'rew') 
 ) t
;   
Другие вопросы по тегам