Как выбрать, где поле, как ABC **** EF ****? - PullRequest
2 голосов
/ 09 июля 2019

У меня есть таблица со следующими полями:

t:([]id:til 5; field:("abc_xy_ef";"abc_ef";"abc_de";"abc_xy_uv";"abc_ef_ghi"))

id field       
---------------
0  "abc_xy_ef" 
1  "abc_ef"    
2  "abc_de"    
3  "abc_xy_uv" 
4  "abc_ef_ghi"

Я бы хотел выбрать только те строки, в которых поле следует за шаблоном "abc_[anything]_ef[anything]", чтобы полученная таблица была:

id field       
---------------
0  "abc_xy_ef" 
1  "abc_ef"    
4  "abc_ef_ghi"

Ответы [ 3 ]

7 голосов
/ 09 июля 2019

Ограничения регулярного выражения в kdb можно преодолеть, поместив несколько предложений where для фильтрации до желаемого результата.

q)select from t where field like "abc*", field like "*ef*"
id field
---------------
0  "abc_xy_ef"
1  "abc_ef"
4  "abc_ef_ghi"

Очевидно, что это не самый эффективный метод, так как после каждого предложения все результатыобработан снова.Вы можете использовать более полную библиотеку регулярных выражений, такую ​​как pcre2 или re2, как указано в документации https://code.kx.com/v2/kb/regex/#regex-libraries

3 голосов
/ 09 июля 2019

Каллум дал правильный ответ - двойной фильтр - лучший подход.

В целях любопытства можно создать "конечный автомат" для обработки более продвинутых регулярных выражений, но это будет ужасно неэффективно в больших масштабах

q)m:({0};{2*x="a"};{3*x="b"};{4*x="c"};{5*x="_"};{5+x="e"};{7*x="f"};{7})
q)match:{7=1 m/x}
q)match["abc_xy_ef"]
1b
q)select from t where match each field
id field
---------------
0  "abc_xy_ef"
1  "abc_ef"
4  "abc_ef_ghi"

Подробности здесь: https://code.kx.com/v2/kb/regex/#regex-in-q

1 голос
/ 09 июля 2019

Как уже упоминалось, KDB в настоящее время не поддерживает это сопоставление регулярному выражению.

Если у вас есть несколько шаблонов или вы можете разбить ваш шаблон на несколько шаблонов, вы также можете сопоставить их в одном условии.

Например, как уже упоминалось в других ответах, вы можете разбить свой шаблон на два - "* abc *" и "* ef *".Затем сопоставьте все шаблоны и выберите строки, соответствующие всем шаблонам.

q)  select from t where all field like/: ("*abc*";"*ef*")

Вы можете добавить больше шаблонов в список.

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

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

q) t:1000000#([]id:til 5; field:("abc_xy_ef";"abc_ef";"abc_de";"abc_xy_uv";"abc_ef_ghi"))
q) \ts select from t where all field like/: ("*abc*";"*ef*") ; / 46 25166144
q) \ts select from t where field like "abc*", field like "*ef*"; / 53 25166144

Аналогично, для приведенных ниже совпадений таблиц по первому шаблону установлено значение 0, поэтому решение с несколькими фильтрами работает быстро.

q) t:([]id:til 1000000;field:1_1000000 {"_" sv 2?'3#enlist 1_.Q.a}\"")
q) \ts select from t where all field like/: ("*abc*";"*ef*") ; / 43 3146000
q) \ts select from t where field like "abc*", field like "*ef*"; / 9 1048816

Таким образом, в принципе это решение потребует более или менее одинакового времени длятот же размер таблицы с различными шаблонами данных.

...