3

EMPLOYEEというテーブルがあり、EMPLOYEE_NAME列があります。
5レコード以上のフレーズが見たいです。
フレーズは最低3文字まで可能です。
たとえば、私のテーブルは次のようになります

EMPLOYEE_NAME
User1
User2
User3
Client1
Client2
Client3
Use1
Aent1
Auser2
ent3

5つ以上のレコードが一致しているため、出力に「Use」と「ent」を表示したいと思います。
ですから、基本的には、5つ以上のレコードのどこかに現れる長さ3の文字シーケンスを見たいのです。
誰かがこれよりも良い解決策を考えられるように、私のシナリオを説明しましょう。
いくつかのデータベースのストアドプロシージャにヒットするWebサービスがあります。
このWebサービスには、ワイルドカード検索を実行できるフィールド(従業員名など)があります。
このWebサービスには、出力のレコードの最大数を指定できる別のフィールドもあります。
したがって、特定のフレーズの検索結果がその数を超えると、応答でエラーが発生します。
そのエラーを引き起こす可能性のあるテストデータを見つける必要があります。
spで使用されるクエリは、検索フレーズの前後に%を配置し、一致するすべてのレコードを返します
。spが使用するデータベース、テーブル、および列を知っており、任意のクエリを直接実行できます。
上で説明したこのクエリソリューションは、私が考えることができる唯一のソリューションでした。
すでに週末なので、以下の答えは試していません。来週最初に試します。
しかし、その間、誰かが解決策を見つけるための別のより良い角度を与えることができれば、それはより良いでしょう。何かご意見は?

4

3 に答える 3

3

これが厄介なポイントです:

"フレーズは、最小 3 文字の任意の文字にすることができます。"

3 つ以上の文字で構成される特定の検索パターンについてテーブルをスキャンしたいということを意味していることを願っています。簡単だ

select employee_id
           , employee_name
from  ( 
    with data as 
        ( select employee_id
                 , employee_name
                 , case 
                     when instr(employee_name, '&search_pattern ) > 0 
                     then 1 
                   else 0 end as i
          from employees )
    select employee_id
           , employee_name
           , sum(i ) over () as cnt
    from data
    where i > 0 )
where cnt >= 5;

ここで、すべての EMPLOYEE_NAME をスキャンしたい場合は、そのテキスト内のすべての文字セットを確立し、他のすべての行でそれらのパターンの出現を検索します。幸運を祈ります。多くのクランチ (または非常に小さなテーブル!) が必要になるため、多くの RAM と多くのコアを備えた猛獣のようなサーバーをお持ちになることを願っています。

あなたのコメントから、この後者のオプションがあなたが望むものであるように見えます。コード内の 3 文字のセグメントをすべて識別するクエリを次に示します。これを使用して、上で投稿したクエリにフィードできる検索パターンのフィードを生成できます。

select employee_name, triple from (
    with data as ( select max(length(employee_name)) as mx from employee )
    select employee_name
           , substr(employee_name, level, ,3) as triple
    from employee
         , data
    connect by level <= data.mx )
where length(triple) = 3;

実際には、DISTINCT トリプルのみを選択する必要がありますが、結果のコンテキストを提供するために、他の列はそのままにしておきます。

このソリューションを拡張して 3 文字以上のセグメントを見つけることは、読者の課題として残されています ;)


「簡単な解決策を見つけたいと思っていました。これまで誰もこの問題に遭遇していないことに驚いています。」

それでは、目を覚ましてコーヒーの匂いを嗅ぐ時間です。 文字列操作は計算コストが高くなります。. 人々がデータベース スキーマの開発に多大な時間と費用を費やす理由は、アドホック パターンの長い文字列をスキャンするために多大な労力を費やす必要がないようにするためです。

あなたのシナリオは、どのデータベースでも見られると予想されるものとは正反対です。そのため、簡単なソリューションはもちろん、事前に用意されたソリューションもありません。

于 2013-01-11T17:11:09.587 に答える
1

名前を 3 つのフレーズに分割するには、 を使用できますSUBSTR(employee_name, x, 3)。ここで、x は 1 から まで実行する必要がありlength(employee_name)-1ます。

substr('Client1',1,3) Cli
substr('Client1',2,3) lie
substr('Client1',3,3) ien
substr('Client1',4,3) ent
substr('Client1',5,3) nt1

これらの位置を生成するには、1 から最大までの数値を含むテーブルを作成できます。または、ちょっとした魔法を使ってその場で数値を生成します。

SELECT level AS x FROM dual CONNECT BY level < max;
1
2
...

組み合わせると、これはすべての従業員名の長さ 3 のすべてのフレーズを取得します。

SELECT id, substr(employee_name, x, 3) AS phrase
  FROM employee
  JOIN (SELECT level AS x FROM dual CONNECT BY level < 27) pos
    ON pos.x < length(employee_name)-1;
1 Use
1 ser
1 er1
...

これで、5 行以上に出現するフレーズを除外するだけで済みます。これは、次の方法で簡単に実行できますGROUP BY phrase HAVING count(DISTINCT id) >= 5

SELECT phrase, count(distinct id)
  FROM (
        SELECT id, substr(employee_name, x, 3) AS phrase
          FROM employee
          JOIN (SELECT level AS x FROM dual CONNECT BY level < 27) pos
            ON pos.x < length(employee_name)-1
       )
 GROUP BY phrase
HAVING count(distinct id) >= 5;
ent 5

例の結果に「使用」を含める必要があるのはなぜですか? 4列だけですか?

于 2013-01-11T21:43:40.900 に答える
1

個人的には、入力文字列で見つかったすべてのトリプレットの入力 n レコードの各文字列を返すパイプ行関数を使用します。この(テーブル)関数を使用して、EMPLOYEE_NAME と group by で結合し、5 を超える個別の従業員名のみを選択します。興味がある場合は、コード例を提供できます。

于 2013-01-11T20:03:31.983 に答える