5

これがシナリオです。いずれかの側の文字列の順序に関係なく、右側の左側のすべての値にまだ一致REGEXPする演算子をシミュレートするために使用する方法。また、左結合とサブクエリを使用して解決策を達成することもできます。INANSI 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
;

したがって、質問には2つの側面があります。

  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 ,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), "}$")

この正規表現は REGEXPではサポートされていないことに注意してください。LIB_MYSQLUDF_PREG でサポートされているはずですが、まだテストしていません。お知らせいたします。他の解決策があるかもしれませんが、REGEXP だけでこれ以上うまくいくとは思えません。

于 2012-12-21T11:26:35.177 に答える