无论顺序如何,REGEXP都匹配另一个组列表中的组字符串 - SQL

bon*_*igo 5 regex mysql sql group-concat

这是场景.如何利用REGEXP模拟IN运算符来匹配右侧左侧的所有值,而不管两侧的字符串顺序如何.还ANSI SQL可以使用左连接和子查询来实现解决方案.

样品表:

Parent table, Child table, Parent_Child.为了不在这个问题上占用更多空间,我只在这里发布了一个问题Group_Concat Child query by Parent.

PID     NAME        CHILDREN    
1       dad john    dave,jill,lina
2       mum sandy   maryam,jack 
3       dad frank   henry,jill 
4       mum kate    maryam  
5       mum jean    dave
Run Code Online (Sandbox Code Playgroud)

预期结果:选择让所有孩子都参与其中的父母.

PID     NAME        CHILDRENREXGEX
3       dad frank   jill,henry
4       mum kate    maryam
5       mum jean    dave
Run Code Online (Sandbox Code Playgroud)

这是REGEXP SQL解决方案:现在问题在于,如果左侧顺序/顺序与右侧不匹配,则不会返回正确的结果.

查询:

select 
    x.pid, x.name, x.children as childrenRexgex
from
    (select 
         p.pid, p.name, group_concat(c.name) as children
     from 
         parent as p
     inner join 
         parent_child as pc on p.pid = pc.pid
     join 
         child as c on pc.cid = c.cid
     group by 
         p.pid
     order by 
         c.name) as x
where 
    'dave,maryam,jill,henry' REGEXP x.children
;
Run Code Online (Sandbox Code Playgroud)

因此,我对这个问题有两个方面的感谢:

  1. 无论订单如何,将左侧的所有名称与用户定义的右侧列表匹配的最佳模式是什么?
  2. 使用的性能可能是什么REGEXP

fth*_*lla 2

您想使用正则表达式,还是其他解决方案也可以?如果我理解正确,这个查询应该给你正确的结果:

select p.pid, parent.name, group_concat(child.name)
from
  (select pid
   from 
     parent_child inner join child
     on parent_child.cid = child.cid
   group by pid
   having sum(child.name in ('dave','henry','maryam','jill'))=count(*)) p
  inner join parent on p.pid=parent.pid
  inner join parent_child on p.pid=parent_child.pid
  inner join child on parent_child.cid=child.cid
group by p.pid
Run Code Online (Sandbox Code Playgroud)

这给出了:

PID     NAME        CHILDRENREXGEX
3       dad frank   jill,henry
4       mum kate    maryam
5       mum jean    dave
Run Code Online (Sandbox Code Playgroud)

无论如何,要使用您的解决方案,我建议您使用group_concat以下命令:

select
  x.pid,
  x.name,
  x.children as childrenRexgex
from(
  select
    p.pid,
    p.name, 
    group_concat(c.name order by c.name) as children,
    count(c.name) as counts
  from
    parent as p inner join parent_child as pc
    on p.pid = pc.pid
    join child as c
    on pc.cid = c.cid
  group by p.pid) as x
where 'dave,henry,jill,maryam'
  REGEXP x.children
Run Code Online (Sandbox Code Playgroud)

并尝试匹配已订购的名称。这与您的查询相同,我只添加了order by c.name内部 group_concat,并且还在 where 条件中订购了字符串。

编辑:如果您确实想使用 REGEXP,由于 MySql 对正则表达式的支持有限,我建议您尝试使用LIB_MYSQLUDF_PREG。这是一个通用解决方案,不适用于标准 MySql 正则表达式。

如果你需要匹配这样的字符串:

One,Two,Three,Four
Run Code Online (Sandbox Code Playgroud)

例如:

Two,Four,Three,One
Run Code Online (Sandbox Code Playgroud)

你必须使用像这样的正则表达式:

"One,Two,Three,Four" REGEXP
"^(?=.*\bTwo\b)(?=.*\bFour\b)(?=.*\bThree\b)(?=.*\bOne\b)"
Run Code Online (Sandbox Code Playgroud)

检查这个问题)这就是它的作用:

  1. \bTwo\b匹配完整单词二,可以是:Two Two, ,Two ,Two,
  2. .*单词 Two 可以在字符串中的任何位置找到.*\bTwo\b
  3. (?=.*\bTwo\b)匹配字符串中任意位置的完整单词“Two”,但忘记位置并从头开始处理下一个术语
  4. 开始匹配其他单词

还缺少什么吗?是的,因为如果我们有 的匹配项"One,Two,Three,Four", 也会"One,Two,Three,Four,Five"匹配。也许有一个更好的正则表达式,但我的想法是:如果它们匹配并且具有相同的长度,那么除了顺序之外它们必须相同。所以我们可以将其添加到正则表达式的末尾:

  1. .{length}$请记住,在所有之前的匹配之后,我们仍然在开头,并且^.{length}$匹配给定长度的字符串

所以最终代码是:

field1="One,Two,Three,Four"
field2="Two,Four,Three,One"

field1 REGEXP CONCAT("^(?=.*\b", 
                     REPLACE(field2, ",", "\b)(?=.*\b"),
                     "\b).{", LENGTH(field1), "}$")
Run Code Online (Sandbox Code Playgroud)

请注意,REGEXP 不支持此正则表达式, LIB_MYSQLUDF_PREG 应该支持它,但我还没有测试它。我会让你知道。可能还有其他解决方案,但我认为仅使用 REGEXP 不可能做得更好。