2009-10-18 86 views
7

目前,我有我的表中的一行:MySQL的Select语句,其中 'IN' 条款

  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",它仍然返回该行。

它不会返回行的唯一方法是如果​​然而,我认为IN()子句将采用我的变量的任何部分,并将其应用于该列。

任何有关我在做什么错误的见解?谢谢。

回答

11

您应该使用the like keyword做煤焦领域的一个部分匹配:

where days like '%1%' 

编辑: VolkerK和卢卡斯·拉林斯基都建议MySQL的find_in_set,这可能比你想要做的like更好。但是,以下有关规范化数据库的建议仍然适用。

但是,不应将多个值存储在单个数据库字段中。相反,可以考虑使用两个表:

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 
    ) 

(或者,这应该是接近,我不正是务必要完成什么,或者你的架构其余的样子,所以这是一个最好的猜测) 。

+0

谢谢。你对改变结构是正确的。我继续这样做。谢谢。 – Dodinas 2009-10-18 22:08:00

+0

“所以这是最好的猜测”:另一个(希望可行的)想法是使用NOT EXISTS子查询,如http://dev.mysql.com/doc/refman/5.1/en/exists-and-not- exists-subqueries.html而不是'x NOT IN(subquery)' – VolkerK 2009-10-19 08:30:08

+0

%like%会给11搜索1,所以它不适合,所以这个答案并不适用于原始问题。 theomega的答案似乎更适用于OP。 – Tarquin 2017-09-10 23:53:38

14

删除IN语句中的行情。语法是:

... WHERE column IN (1,2,3) 

而不是你用它

... WHERE column IN ('1,2,3') 

也可见于documentation,还有更多的例子。

+0

其实,对不起,我需要一些澄清。我在这里做错了事。如果我使用:WHERE IN IN(1)天,它会正确删除它并返回空结果。但是,如果我使用:WHERE IN(3)天,它不会返回空查询。我会认为它应该删除查询,因为'3'在查询中?有任何想法吗? – Dodinas 2009-10-18 21:43:52

+0

我想这是因为它将“1,3,5”转换为int(以逗号停留),然后看到它匹配。 – Yuliy 2009-10-18 21:45:58

+0

不知道为什么这不是原始文章中给出的方案的接受答案 - 尽管我接受接受的答案提供了纠正错误编码习惯的建议。 – Tarquin 2017-09-10 23:51:50

0

天不包含字符串列表。它包含一个字符串。 {'1'}中的字符串之一是字符串“1,3,5”吗?很明显,答案是否定的。无论是重构天到一个不同的表,或者准备做更多的字符串操作

2

如果我正确理解您的问题,您希望将varchar字段的内容视为逗号分隔列表,并测试此列表是否不包含特定值。为此,您需要find_in_set(str, strlist)函数。
但请记住,在这种情况下,MySQL不能使用索引,并且您的查询将始终需要全表扫描。它可能最好不要将结构化数据(并在单个元素上运行比较)存储在单个列中,而是使用其他响应中建议的另一个表和JOIN。

5

我想你想查询的是:

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 

但是你应该认真考虑标准化的数据库,让每一天都有它自己的行。