17

この質問は、MYSQL結合結果セットのWhere句のIN()中にワイプされた結果に続きますか?

だから、質問の短いバージョン。GROUP_CONCATによって返された文字列を、IN()がループする複数の項目のリストとして扱うコンマ区切りの式リストに変換するにはどうすればよいですか?

注意:MySQLドキュメントは、IN()が「式リスト」として使用する「(コンマ、区切り、リスト)」を参照しているようです。興味深いことに、IN()のページは多かれ少なかれMySQLドキュメントの唯一のページのようです。式リストを参照します。したがって、配列または一時テーブルを作成することを目的とした関数がここで使用されるかどうかはわかりません。


質問の長い例ベースのバージョン:次のような2テーブルDBから:

SELECT id, name, GROUP_CONCAT(tag_id) FROM person INNER JOIN tag ON person.id = tag.person_id GROUP BY person.id;
+----+------+----------------------+
| id | name | GROUP_CONCAT(tag_id) |
+----+------+----------------------+
|  1 | Bob  | 1,2                  |
|  2 | Jill | 2,3                  |
+----+------+----------------------+

文字列を使用するため、これを(1 = X)AND(2 = X)..と論理的に等価として扱うにはどうすればよいですか。

SELECT name, GROUP_CONCAT(tag.tag_id) FROM person LEFT JOIN tag ON person.id = tag.person_id 
GROUP BY person.id HAVING ( ( 1 IN (GROUP_CONCAT(tag.tag_id) ) ) AND ( 2 IN (GROUP_CONCAT(tag.tag_id) ) ) );
Empty set (0.01 sec)

... GROUP_CONCATの結果がリストとして扱われるものに変換されるため、Bobの場合は次のようになります。

SELECT name, GROUP_CONCAT(tag.tag_id) FROM person INNER JOIN tag ON person.id = tag.person_id AND person.id = 1 
GROUP BY person.id HAVING ( ( 1 IN (1,2) ) AND ( 2 IN (1,2) ) );
+------+--------------------------+
| name | GROUP_CONCAT(tag.tag_id) |
+------+--------------------------+
| Bob  | 1,2                      |
+------+--------------------------+
1 row in set (0.00 sec)

...そしてジルにとって、それは以下と同等です:

SELECT name, GROUP_CONCAT(tag.tag_id) FROM person INNER JOIN tag ON person.id = tag.person_id AND person.id = 2 
GROUP BY person.id HAVING ( ( 1 IN (2,3) ) AND ( 2 IN (2,3) ) );
Empty set (0.00 sec)

...したがって、全体的な結果は、HAVING COUNT(DISTINCT ...)を使用しないすべてのリストされたタグを必要とする排他的な検索句になりますか?

(注:このロジックはANDなしで機能し、文字列の最初の文字に適用されます。例:

SELECT name, GROUP_CONCAT(tag.tag_id) FROM person LEFT JOIN tag ON person.id = tag.person_id 
  GROUP BY person.id HAVING ( ( 2 IN (GROUP_CONCAT(tag.tag_id) ) ) );
+------+--------------------------+
| name | GROUP_CONCAT(tag.tag_id) |
+------+--------------------------+
| Jill | 2,3                      |
+------+--------------------------+
1 row in set (0.00 sec)
4

2 に答える 2

45

を使用する代わりにIN()、を使用するFIND_IN_SET()こともオプションでしょうか?

http://dev.mysql.com/doc/refman/5.0/en/string-functions.html#function_find-in-set

mysql> SELECT FIND_IN_SET('b','a,b,c,d');
    -> 2

これは、質問の問題の例に基づく完全な例であり、質問の以前の編集で質問者によってテストされたことが確認されています。

SELECT name FROM person LEFT JOIN tag ON person.id = tag.person_id GROUP BY person.id 
  HAVING ( FIND_IN_SET(1, GROUP_CONCAT(tag.tag_id)) ) AND ( FIND_IN_SET(2, GROUP_CONCAT(tag.tag_id)) );
+------+
| name |
+------+
| Bob  |
+------+
于 2011-01-10T19:53:51.330 に答える
5

分割セパレータを使用して文字列を配列として渡し、結果を処理する関数でそれを分解できます。

簡単な例として、「one | two | tree | four | five」のような文字列配列があり、2つが配列に含まれているかどうかを知りたい場合は、次のように実行できます。

create function str_in_array( split_index varchar(10), arr_str varchar(200), compares varchar(20) )
  returns boolean
  begin
  declare resp boolean default 0;
  declare arr_data varchar(20);

  -- While the string is not empty
  while( length( arr_str ) > 0  ) do

  -- if the split index is in the string
  if( locate( split_index, arr_str ) ) then

      -- get the last data in the string
    set arr_data = ( select substring_index(arr_str, split_index, -1) );

    -- remove the last data in the string
    set arr_str = ( select
      replace(arr_str,
        concat(split_index,
          substring_index(arr_str, split_index, -1)
        )
      ,'')
    );
  --  if the split index is not in the string
  else
    -- get the unique data in the string
    set arr_data = arr_str;
    -- empties the string
    set arr_str = '';
  end if;

  -- in this trivial example, it returns if a string is in the array
  if arr_data = compares then
    set resp = 1;
  end if;

 end while;

return resp;
end
|

delimiter ;

このメソッドで動作する便利なmysql関数のセットを作成したいと思います。興味のある方はご連絡ください。

その他の例については、http://blog.idealmind.com.br/mysql/how-to-use-string-as-array-in-mysql-and-work-with/にアクセスしてください。

于 2012-07-22T15:42:25.747 に答える