2017-04-13 3 views
0

私は、ユーザーからの統計を格納する大規模なデータベース(200万行以上)を持っています。ユーザーには、パーツを含む一意のID(たとえば、ハッシュされたMACアドレス)があります。同じ列に3つ以上の必須単語が含まれているMySQLデータベース行を選択するにはどうすればよいですか?

"AAAAAA-BBBBBB-CCCCCC-DDDDDD-EEEEEE-FFFFFFF" たまに

ユニークIDの変更の一部と、それは例えばです: 例一意のID文字列がある

「ZZZZZZ-私はユーザを特定し、少なくとも3つ(または異なる値)の一意のID部分が一致するすべての行を、PHPを使用して選択したいと考えています。私がそれを行うのに使うことができる有用な構文はありますか?私は少なくとも1つの一意のID部分を含むすべての行を選択してから、 " - "文字で配列に展開し、少なくとも3つの同じ単語が含まれているかどうかを調べることができますが、これは最速の方法ではないと思います。

WHERE `UniqueID` REGEXP 'AAAAAA|BBBBBB|CCCCCC|DDDDDD|EEEEEE|FFFFFFF'; 

しかし、唯一の場合は3〜6の言葉の試合を選択:

基本的に、私はのようなものを使用したいと思います。

+1

あなたの一意のIDをに分割する必要がある

function SplitUniqueIDKeepDelimeters($UniqueID, $Delimeter = "-"){ $UniqueIDParts = array(); $Remaining = $UniqueID; $pos = strpos($Remaining, $Delimeter); $firstPart = true; while ($pos !== false) { $Part = substr($Remaining,0,$pos + 1); if(!$firstPart){ $Part = $Delimeter.$Part; } $firstPart = false; $UniqueIDParts[] = $Part; $Remaining = substr($Remaining,$pos+1); $pos = strpos($Remaining, $Delimeter); } if(!$firstPart){ $Remaining = $Delimeter.$Remaining; } $UniqueIDParts[] = $Remaining; return $UniqueIDParts; } 

はその後@ krishKMの回答に基づいて、私は選択構文を作成しましたこれははるかに簡単です。また、マッチのポジションは一致する必要がありますか? –

+0

あなたは[同じような種類のデータを常に類似した文字で書かれたクレジットカードのスタイルがあれば[これは](http://stackoverflow.com/questions/17392197/selecting-part-of-a-field -with-a-regex)または[これは](http://stackoverflow.com/questions/1326063/using-columns-in-a-regexp-in-mysql)と[これは](http://stackoverflow.com/questions/9315647/regex-credit-card-number-tests) – OldPadawan

+0

ありがとうございます!残念ながら、列には、同じ順序ではなく、「一意のID部分」を含めることができます。一意のIDは、短くすることができます(たとえば、6個の代わりに4個など)。これらの部分は通常、ハッシュされたハードウェア情報です(ランダムな長さの数字、最大12文字の長さです)。 – Mona

答えて

1

パフォーマンスを点検したいと思うかもしれない

は、文字列があなたのid文字列内で使用可能であるかどうかを確認するINSTRを使用して、このクエリを考えてみましょう。私は部分を抽出するためにsubstring_indexを使用しました。 id文字列の一部を分割または抽出して一時テーブルを作成することに興味があっても、この回答のために無視することができます。

理想的には、keyword1、keyword2 & keyword3をパラメータとして使用して独自のストアドプロシージャを作成し、検索を実行して結果を返すことができます。

ここで、キーワード1、2 & 3がID文字列に含まれているかどうかを調べます。

select 
    'ZZZZZZ-BBBBBB-CCCCCC-DDDDDD-EEEEEE-XXXXXXX' as Id, 
    substring_index('ZZZZZZ-BBBBBB-CCCCCC-DDDDDD-EEEEEE-XXXXXXX','-', 1) as part1, 
    substring_index(substring_index('ZZZZZZ-BBBBBB-CCCCCC-DDDDDD-EEEEEE-XXXXXXX','-', 2),'-', -1) as part2, 
    substring_index(substring_index('ZZZZZZ-BBBBBB-CCCCCC-DDDDDD-EEEEEE-XXXXXXX','-', 3),'-', -1) as part3, 
    substring_index(substring_index('ZZZZZZ-BBBBBB-CCCCCC-DDDDDD-EEEEEE-XXXXXXX','-', 4),'-', -1) as part4, 
    substring_index(substring_index('ZZZZZZ-BBBBBB-CCCCCC-DDDDDD-EEEEEE-XXXXXXX','-', 5),'-', -1) as part5, 
    substring_index(substring_index('ZZZZZZ-BBBBBB-CCCCCC-DDDDDD-EEEEEE-XXXXXXX','-', 6),'-', -1) as part6 
from dual 
WHERE 

    instr('ZZZZZZ-BBBBBB-CCCCCC-DDDDDD-EEEEEE-XXXXXXX','BBBBBB') >= 1 -- keyword1 
    and instr('ZZZZZZ-BBBBBB-CCCCCC-DDDDDD-EEEEEE-XXXXXXX','CCCCCC') >= 1 -- keyword2 
    and instr('ZZZZZZ-BBBBBB-CCCCCC-DDDDDD-EEEEEE-XXXXXXX','DDDDDD') >= 1 -- keyword3 
; 

EDIT 上記のクエリでは、あなたのロジックを追加することができます動作していますか。

select 
    'ZZZZZZ-BBBBBB-CCCCCC-DDDDDD-EEEEEE-XXXXXXX' as Id 


from dual 
WHERE 
    (
    -- below logic gives true when 3 or more keywords are found. change this accordingly 
     (instr('ZZZZZZ-BBBBBB-CCCCCC-DDDDDD-EEEEEE-XXXXXXX',ik1) >0)+ 
     (instr('ZZZZZZ-BBBBBB-CCCCCC-DDDDDD-EEEEEE-XXXXXXX',ik2) >0)+ 
     (instr('ZZZZZZ-BBBBBB-CCCCCC-DDDDDD-EEEEEE-XXXXXXX',ik3) >0)+ 
     (instr('ZZZZZZ-BBBBBB-CCCCCC-DDDDDD-EEEEEE-XXXXXXX',ik4) >0)+ 
     (instr('ZZZZZZ-BBBBBB-CCCCCC-DDDDDD-EEEEEE-XXXXXXX',ik5) >0)+ 
     (instr('ZZZZZZ-BBBBBB-CCCCCC-DDDDDD-EEEEEE-XXXXXXX',ik6) >0) 
    ) >=3 

; 
+0

お時間をありがとう。私はそれをテストし、〜200万行のデータベースから選択するのに5秒かかる。しかし、私は1つのことを理解していない:クエリは6つのキーワードを検索し、3つ以上の一致が成功した場合のみ成功する。 "とinstr( 'UniqueID'、' xxxxxxxxx ')> = 1 - keyword4"を追加すると、クエリは機能しません。だから私は "OR"を使用する必要があると思うが、3つの一致がある場合にのみ選択する... – Mona

+0

@Mona編集を参照 –

+0

恐ろしい!ご協力ありがとうございました。私は、PHPを分離した "答え"でどのように使ったのかを投稿します。 – Mona

0

@krishKMのおかげで、私はPHPを使用して、私の独自のIDを選択するための最善の解決策を見つけました。

まず、配列に一意のIDパーツを配置する機能を作ったが、両側に「区切り文字」を保持していました。 IDの部分が非常に短い場合など、誤った選択を防止するのに役立ちます。

function GenerateSelectingString($UniqueIDParts, $RowName = "UniqueID", $HowManyMatches = 3){ 
    $First = true; 
    $FinishedString = " ("; 
    foreach ($UniqueIDParts as $key => $value){ 
     if(!$First){ 
      $FinishedString .= "+"; 
     } 
     $First = false; 
     $FinishedString .= "(instr(`".$RowName."`,'".$value."') > 0)"; 

    } 
    $FinishedString .= ") >=".$HowManyMatches; 
    return $FinishedString; 
} 

テスト:

$TestArray = SplitUniqueIDKeepDelimeters("21680-7886-2761736077-72316693-753974682-041548389245"); 
$TestSelectString = GenerateSelectingString($TestArray, "UniqueID"); 

echo "Unique ID parts array:<br>"; 
var_dump($TestArray); 
echo "<br><br>Query String:<br>"; 
echo $TestSelectString; 
echo "<br>"; 

$sql2 = "SELECT * FROM `Statistics`.`Statistics` WHERE ".$TestSelectString. " order by `lognumber` DESC;"; 
    $result2 = mysqli_query($conn, $sql2); 
    if (mysqli_num_rows($result2) > 0) { 
    while($row2 = mysqli_fetch_assoc($result2)) { 
    echo "<br>"; 
    var_dump($row2); 
    echo "<br>"; 
    } 
} 
else{ 
    echo "<br>".mysqli_errno($conn) . ": " . mysqli_error($conn) . "\n"; 
} 

出力:

Unique ID parts array: array(6) { [0]=> string(6) "21680-" [1]=> string(6) "-7886-" [2]=> string(12) "-2761736077-" [3]=> string(10) "-72316693-" [4]=> string(11) "-753974682-" [5]=> string(13) "-041548389245" } 

Query String: ((instr(`UniqueID`,'21680-') > 0)+(instr(`UniqueID`,'-7886-') > 0)+(instr(`UniqueID`,'-2761736077-') 
> 0)+(instr(`UniqueID`,'-72316693-') > 0)+(instr(`UniqueID`,'-753974682-') > 0)+(instr(`UniqueID`,'-041548389245') > 0)) >=3 

array(60) { ... 
関連する問題