如何从像 abc****ef**** 这样的字段中 select?

How to select from where field like abc****ef****?

我有一个包含以下字段的 table:

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"

我只想 select 字段遵循模式 "abc_[anything]_ef[anything]" 的行,这样得到的 table 将是:

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

可以通过放置多个 where 子句来过滤到所需的结果来克服 kdb 中正则表达式的限制

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

Callum 给出了正确答案 - 双过滤器是最好的方法。

出于好奇,可以创建一个 "state machine" 来处理更高级的正则表达式,但在大规模情况下效率会非常低

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

正如其他人所说,KDB目前不支持这种正则表达式匹配。

如果您有多个模式或可以将模式分成多个模式,那么您也可以在一个条件下匹配它们。

例如,如其他答案中所述,您可以将模式拆分为两个 - “*abc*”和“*ef*”。然后匹配所有模式和 select 与所有模式匹配的行。

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

您可以向列表中添加更多模式。

性能会因数据模式而异。如果第一个模式有更多匹配项,那么此解决方案 运行 比 where 子句中的多个条件更快,反之亦然。

下面的示例通过在您的示例 table 中复制记录来创建 table 以增加第一个模式的匹配。这个解决方案 运行 很快,因为第一个模式有多个匹配项。

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

类似地,对于下面的 table 个匹配项,第一个模式是 0,因此多重过滤器解决方案 运行s 快。

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

所以基本上,对于具有不同数据模式的相同 table 大小,此解决方案将花费或多或少相同的时间。