5

这是场景。无论两侧的字符串顺序如何,如何利用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

预期结果:选择让所有孩子都参与某事的家长。

PID     NAME        CHILDRENREXGEX
3       dad frank   jill,henry
4       mum kate    maryam
5       mum jean    dave

这是 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
;

因此,对于这个问题,我会欣赏两个方面:

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

1 回答 1

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

这给出了:

PID     NAME        CHILDRENREXGEX
3       dad frank   jill,henry
4       mum kate    maryam
5       mum jean    dave

无论如何,要使用您的解决方案,我建议您使用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

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

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

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

One,Two,Three,Four

例如,这个:

Two,Four,Three,One

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

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

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

  1. \bTwo\b匹配全词二,可以是:Two Two, ,Two ,Two,
  2. .*可以在字符串中的任何位置找到单词二.*\bTwo\b
  3. (?=.*\bTwo\b)匹配全词二,字符串中的任何位置,但忘记位置并从头开始匹配下一个词
  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), "}$")

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

于 2012-12-21T11:26:35.177 回答