【问题标题】:MySQL Select Statement, WHERE 'IN' ClauseMySQL Select 语句,WHERE 'IN' 子句
【发布时间】:2010-12-07 20:24:12
【问题描述】:

我的表中目前有以下行:

         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() 子句会占用我的变量的任何部分并将其应用于该列。

对我在这里做错了什么有任何见解吗?谢谢。

【问题讨论】:

    标签: php sql mysql select


    【解决方案1】:

    删除 IN 语句中的引号。语法是:

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

    而不是像你使用的那样

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

    另见 IN 上的documentation,还有更多示例。

    【讨论】:

    • 其实,抱歉,我需要澄清一下。我在这里做错了什么。如果我使用:WHERE days IN (1),它会正确删除它并返回一个空结果。但是如果我使用:WHERE days IN (3),它不会返回一个空查询。我认为它应该删除查询,因为“3”在查询中?有什么想法吗?
    • 我猜这是因为它将“1,3,5”转换为int(停在逗号处),然后发现它匹配。
    • 不知道为什么这不是原始帖子中给出的场景的可接受答案 - 尽管我接受接受的答案提供了纠正不良编码习惯的建议。
    【解决方案2】:

    您应该使用the like keyword 对 char 字段进行部分匹配:

    where days like '%1%'
    

    编辑: VolkerK 和 Lukas Lalinsky 都建议使用 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
        )
    

    (或者,应该很接近;我不完全确定您要完成什么或您的架构的其余部分是什么样的,所以这是一个最好的猜测)。

    【讨论】:

    • 谢谢。你对改变结构是正确的。我继续这样做。谢谢。
    • “所以这是一个最好的猜测”:另一个(希望是可行的)想法是使用dev.mysql.com/doc/refman/5.1/en/… 中描述的 NOT EXISTS 子查询,而不是 x NOT IN (subquery)
    • %like% 会给出 11 来搜索 1,所以它并不真正适合,所以这个答案并不真正适用于原始问题。 theomega 的回答似乎更适用于 OP。
    【解决方案3】:

    我想你想要的查询是:

    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
    

    但是您应该认真考虑规范化数据库,以便每天都有自己的行。

    【讨论】:

      【解决方案4】:

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

      【讨论】:

        【解决方案5】:

        days 不包含字符串列表。它包含一个字符串。字符串“1,3,5”是否在 {'1'} 中的一个字符串内?显然答案是否定的。要么将 days 重构到不同的表中,要么准备进行更多的字符串操作

        【讨论】:

          猜你喜欢
          • 2016-12-29
          • 1970-01-01
          • 2018-03-08
          • 1970-01-01
          • 2012-08-12
          • 1970-01-01
          • 2011-01-12
          • 2016-03-25
          • 2021-12-23
          相关资源
          最近更新 更多