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
;