MySQLクエリがカンマ区切りの文字列で値を見つける


90

COLORS (varchar(50))テーブルSHIRTSに、などのカンマ区切りの文字列を含むフィールドがあります1,2,5,12,15,。使用可能な色を表す各数値。

クエリselect * from shirts where colors like '%1%'を実行してすべての赤いシャツ(color = 1)を取得すると、灰色(= 12)とオレンジ(= 15)のシャツも取得されます。

1を含むすべての色ではなく、色1のみを選択するようにクエリを書き換えるにはどうすればよいですか?


6
正規表現を使用してこれを行うこともできますが、シャツの色を別のテーブル(色)に分割し、color / shirtのIDを使用して結合テーブル(shirt_colors)を使用してそれらをリンクすることをお勧めします。
ceejayoz

私は6つの答えを信じることができない何も ...それらのは、MySQLのSETデータ型を言及していない
ColinM

回答:


185

古典的な方法は、左右にカンマを追加することです。

select * from shirts where CONCAT(',', colors, ',') like '%,1,%'

しかし、find_in_setも機能します。

select * from shirts where find_in_set('1',colors) <> 0

find_in_setを試しましたが、入力したカラー値に関係なく同じ結果が返されます...何か提案はありますか?
bikey77

@ bikey77:多分これが問題だ、とドキュメントは言う:最初の引数にコンマ(“、”)文字が含まれている場合、この関数は正しく機能しません。
Andomar

私の間違い、同じダミー値による論理的な間違いでした。正常に動作します。ありがとう!
bikey77

@Andomar私はあなたの答えを見つけた前に、私は、INに苦しんでWASTが、あなたは魅力のような仕事です...ありがとうございました...
PHPメンター

2
Find_in_setはインデックスを使用しないため、パフォーマンスに影響があります
Kamran Shahid、



11

これは確かに機能し、実際に試してみました:

lwdba@localhost (DB test) :: DROP TABLE IF EXISTS shirts;
Query OK, 0 rows affected (0.08 sec)

lwdba@localhost (DB test) :: CREATE TABLE shirts
    -> (<BR>
    -> id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
    -> ticketnumber INT,
    -> colors VARCHAR(30)
    -> );<BR>
Query OK, 0 rows affected (0.19 sec)

lwdba@localhost (DB test) :: INSERT INTO shirts (ticketnumber,colors) VALUES
    -> (32423,'1,2,5,12,15'),
    -> (32424,'1,5,12,15,30'),
    -> (32425,'2,5,11,15,28'),
    -> (32426,'1,2,7,12,15'),
    -> (32427,'2,4,8,12,15');
Query OK, 5 rows affected (0.06 sec)
Records: 5  Duplicates: 0  Warnings: 0

lwdba@localhost (DB test) :: SELECT * FROM shirts WHERE LOCATE(CONCAT(',', 1 ,','),CONCAT(',',colors,',')) > 0;
+----+--------------+--------------+
| id | ticketnumber | colors       |
+----+--------------+--------------+
|  1 |        32423 | 1,2,5,12,15  |
|  2 |        32424 | 1,5,12,15,30 |
|  4 |        32426 | 1,2,7,12,15  |
+----+--------------+--------------+
3 rows in set (0.00 sec)

試してみる !!!


@rolandomysqldbaさん、クエリをテストしましたが、問題なく動作しますが、変更を加える必要があります。列のカラー値が1、2のすべてのシャツを取得したいとします。
Ahsan Saeed

6

色のセットが多かれ少なかれ固定されている場合、最も効率的で最も読みやすい方法は、アプリで文字列定数を使用し、クエリでMySQLのSETタイプを使用FIND_IN_SET('red',colors)することです。FIND_IN_SETSETタイプを使用する場合、MySQLは1つの整数を使用してすべての値を格納し、バイナリを使用します"and"演算を存在を確認します。これは、コンマ区切りの文字列をスキャンするよりも効率的です。

のように内部的に格納される、ように内部的に格納されることになるとように内部的に格納されることになります。値として格納されることになる()とのように()。SET('red','blue','green')'red'1'blue'2'green'4'red,blue'31|2'red,green'51|4



3

実際にデータベーススキーマを修正して、3つのテーブルを作成する必要があります。

shirt: shirt_id, shirt_name
color: color_id, color_name
shirtcolor: shirt_id, color_id

次に、赤いシャツをすべて検索するには、次のようなクエリを実行します。

SELECT *
FROM shirt, color
WHERE color.color_name = 'red'
  AND shirt.shirt_id = shirtcolor.shirt_id
  AND color.color_id = shirtcolor.color_id

8
@Blindy:これは、OPがデータベーススキーマに対する編集権限を持っていると想定している場合にのみ当てはまります。データベースを再設計し、データを移行し、すべてのクライアントをリファクタリングする時間があります。そして、このクエリの複雑さの軽減は、アプリケーションの他の部分の複雑さの増加よりも重要です。
Andomar

1
@Andomarは、行の取得のサイズ制限に遭遇し、彼の「レコード」が切り取られたときに、本当の楽しみが始まります。
ブリンディ

3
@Blindy:要点を逃しています。彼が最善の解決策を持っていると私は主張していませんが、誰もが彼の好みに合わせて彼の環境を再設計する自由を持っているわけではありません
Andomar

私は@Andomarに同意します
アダムB


0

1. MySQLの場合:

SELECT FIND_IN_SET(5, columnname) AS result 
FROM table

2. Postgres SQLの場合:

SELECT * 
FROM TABLENAME f
WHERE 'searchvalue' = ANY (string_to_array(COLUMNNAME, ','))

select * 
from customer f
where '11' = ANY (string_to_array(customerids, ','))

0

以下の機能で実現できます。

次のクエリを実行して関数を作成します。

DELIMITER ||
CREATE FUNCTION `TOTAL_OCCURANCE`(`commastring` TEXT, `findme`     VARCHAR(255)) RETURNS int(11)
NO SQL
-- SANI: First param is for comma separated string and 2nd for string to find.
return ROUND (   
    (
        LENGTH(commastring)
        - LENGTH( REPLACE ( commastring, findme, "") ) 
    ) / LENGTH(findme)        
);

そして、このようにこの関数を呼び出します

msyql> select TOTAL_OCCURANCE('A,B,C,A,D,X,B,AB', 'A');

-7

すべての答えは本当に正しくありません、これを試してください:

select * from shirts where 1 IN (colors);
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.