現在、テーブルに次の行があります。
course_data:
user_id days <-- This is a varchar column.
405 1,3,5
そして、私は次のSELECTステートメントを実装しようとしています。
SELECT usrID, usrFirst, usrLast, usrEmail
FROM tblUsers
WHERE usrID NOT IN
(
SELECT users.usrID
FROM
`course_data` courses,
`tblUsers` users
WHERE
days IN ('$day')
)
GROUP BY usrID
ORDER BY usrID
基本的に、$ day変数に「1、3、または5」が含まれている場合は、その行(ユーザー405)を省略します。
たとえば、$day = "1"
の場合、空のクエリを返す必要があります(数値「1」が列「1,3,5」にあるため)。
しかし、私はこれが事実であるとは思いませんでした。 $day = "1"
であっても、その行を返します。
行を返さない唯一の方法は、$day= "1,3,5."
の場合です。それでも、IN()句は変数の任意の部分を取り、それをその列に適用すると思いました。
私がここで間違っていることについての洞察はありますか?ありがとう。
Charフィールドの部分一致を行うには、 like
キーワード を使用する必要があります。
where days like '%1%'
編集:VolkerKとLukasLalinskyはどちらもMySQLのfind_in_set
、これはおそらくlike
よりもやりたいことの方が良いでしょう。ただし、データベースの正規化に関する次の推奨事項は引き続き適用されます。
ただし、単一のデータベースフィールドに複数の値を格納しないでください。代わりに、次の2つのテーブルの使用を検討してください。
course_data:
user_id
course_days:
user_id
day_number
次に、次のデータがあります。
course_data:
user_id
405
course_days
user_id day_number
405 1
405 3
405 5
その後、このスキーマを正しくクエリできます。例えば:
select cd.user_id
from course_data as cd
where cd.user_id not in
(
select course_days.user_id
from course_days
where course_days.user_id = cd.user_id
and course_days.day_number = 1
)
(または、それは近いはずです。私はあなたが何を達成しようとしているのか、またはスキーマの残りの部分がどのように見えるのか正確にわからないので、これは最良の推測です) 。
INステートメントの引用符を削除します。構文は次のとおりです。
... WHERE column IN (1,2,3)
あなたがそれを使ったようにではなく
... WHERE column IN ('1,2,3')
INの documentation も参照してください。他にも例があります。
私はあなたが望むクエリは次のとおりだと思います:
SELECT usrID, usrFirst, usrLast, usrEmail
FROM tblUsers
WHERE usrID NOT IN (
SELECT user_id
FROM course_data
WHERE find_in_set(?, days) > 0
)
ORDER BY usrID
ただし、データベースを正規化して、毎日独自の行を持つようにすることを真剣に検討する必要があります。
私があなたの質問を正しく理解している場合は、varcharフィールドの内容をコンマ区切りのリストとして扱い、このリストに特定の値が含まれていないかどうかをテストする必要があります。そのためには find_in_set(str、strlist) 関数が必要です。
ただし、その場合、MySQLはインデックスを使用できず、クエリでは常に全表スキャンが必要になることに注意してください。それ かもしれない 構造化データを単一の列に格納する(および単一の要素で比較を実行する)のではなく、他の応答で提案されているように別のテーブルとJOINを使用することをお勧めします。
daysは文字列のリストを保持しません。単一の文字列を保持します。文字列「1,3,5」は{'1'}の文字列の1つに含まれていますか?明らかに答えはノーです。日を別のテーブルにリファクタリングするか、より多くの文字列操作を行う準備をしてください