2009-10-18 4 views
7

나는 현재 나의 테이블의 다음 행이 있습니다MySQL을 선택 성명, '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 

을, I $ day 변수에 '1, 3 또는 5'가 포함되어 있으면 해당 행 (사용자 405 포함)을 생략 할 수 있습니다.

예를 들어, $day = "1" 인 경우 "1"이 열 "1,3,5"에 있기 때문에 빈 쿼리를 반환해야합니다.

그러나이 경우는 아닙니다. $day = "1"에도 불구하고 여전히 해당 행을 반환합니다.

행을 반환하지 않는 유일한 방법은 $day= "1,3,5."입니다. 그러나 IN() 절이 내 변수의 일부를 취해 해당 열에 적용한다고 생각했습니다.

내가 여기서 잘못하고있는 것에 대한 통찰력이 있습니까? 감사.

답변

11

을 할 수 있도록 준비 MySQL의 find_in_set을 제안하십시오. 원하는 작업에 대해 아마도 like보다 좋습니다. 그러나 데이터베이스 정상화에 대한 다음 권장 사항이 여전히 적용됩니다.

그러나 단일 데이터베이스 필드에 여러 값을 저장하면 안됩니다. 대신, 두 개의 테이블을 사용하는 것이 좋습니다 :

course_data: 
    user_id 
    405 

course_days 
    user_id day_number 
    405  1 
    405  3 
    405  5 

그런 다음 올바르게 스키마를 조회 할 수 있습니다

course_data: 
    user_id 

course_days: 
    user_id 
    day_number 

그런 다음, 다음과 같은 데이터를 가질 것이다. 예를 들면 :

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

+0

"이것은 가장 좋은 추측입니다."또 다른 (희망적으로 실현 가능한) 아이디어는 NOT EXISTS 서브 쿼리를 http://dev.mysql.com/doc/refman/5.1/en/exists-and-not-news에 설명 된대로 사용하는 것입니다. 'x NOT IN (subquery) '대신에 exist-subqueries.html – VolkerK

+0

%는 1을 검색하기 위해 11을 주므로, 실제로 적합하지 않으므로이 답변은 원래 질문에는 실제로 적용되지 않습니다. theomega의 답변은 OP에 더 적합하게 보입니다. – Tarquin

14

IN 문에서 따옴표를 제거하십시오. 구문은 다음과 같습니다

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

당신이 그것을 사용하지

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

로도에 documentation 자세한 예가있다.

+0

사실, 죄송합니다. 설명이 필요합니다. 나는 여기서 뭔가 잘못하고있다. 내가 사용하는 경우 : IN 일 (1) 일, 그것을 제대로 제거하고 빈 결과를 반환합니다. 하지만 내가 사용하는 경우 : IN 일 (3) 일 동안 빈 쿼리를 반환하지 않습니다. '3'이 쿼리에 있기 때문에 쿼리를 제거해야한다고 생각합니까? 어떤 아이디어? – Dodinas

+0

"1,3,5"를 int (쉼표로 멈춤)로 변환하고 일치하는 것으로 간주하기 때문에 이것이라고 생각합니다. – Yuliy

+0

원래 게시물에 제시된 시나리오에 대해 허용 된 답변이 아닌 이유를 잘 모릅니다. 허용 된 답변은 잘못된 코딩 습관을 수정하는 방법에 대한 조언을 제공합니다. – Tarquin

0

일에는 문자열 목록이 없습니다. 단일 문자열을 보유합니다. { '1'}의 문자열 중 하나에 '1,3,5'문자열이 있습니까? 분명 대답은 아니오입니다.

where days like '%1%' 

편집 : VolkerK와 루카스 랄 린스키 모두 다른 테이블에 어느 리팩토링 일이, 또는 당신은 문자 필드의 부분 일치 할 the like keyword를 사용해야 더 문자열 조작

2

질문을 올바르게 이해하면 varchar 필드의 내용을 쉼표로 구분 된 목록으로 처리하고이 목록에 특정 값이 없는지 테스트하십시오. 이를 위해서는 find_in_set(str, strlist) 기능이 필요합니다.
그러나이 경우 MySQL은 인덱스를 사용할 수 없으므로 쿼리에 항상 전체 테이블 스캔이 필요합니다. 단일 열에 구조화 된 데이터를 저장하지 않고 (단일 요소에 대한 비교를 실행하는 것이 더 좋음) 다른 응답에서 제안 된 것처럼 다른 테이블과 JOIN을 사용하는 것이 좋습니다.

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 

그러나 매일이 자신의 행입니다 가질 수 있도록 당신이 심각하게 데이터베이스를 정상화 고려해야합니다

5

내가 원하는 쿼리라고 생각합니다.