2009-10-18 34 views
7

Tôi hiện đang có hàng sau trong bảng của tôi:MySQL Chọn Statement, WHERE 'TRÊN' khoản

  course_data: 
      user_id  days  <-- This is a varchar column. 
       405   1,3,5 

và tôi đang cố gắng để thực hiện các câu lệnh SELECT như sau:

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 

Về cơ bản, tôi muốn bỏ qua hàng đó (với người dùng 405) nếu biến $ day bao gồm '1, 3 hoặc 5'.

Ví dụ: nếu $day = "1", nó sẽ trả về truy vấn trống (vì số "1" nằm trong cột "1,3,5").

Tuy nhiên, tôi không thấy điều này xảy ra. Mặc dù $day = "1", nó vẫn trả về hàng đó.

Cách duy nhất để nó không trả về hàng là $day= "1,3,5." Tuy nhiên, tôi nghĩ rằng mệnh đề IN() sẽ lấy bất kỳ phần nào của biến của tôi và áp dụng nó vào cột đó.

Mọi thông tin chi tiết về những gì tôi đang làm sai ở đây? Cảm ơn.

Trả lời

11

Bạn nên sử dụng the like keyword để làm một trận đấu một phần của các lĩnh vực char:

where days like '%1%' 

Edit: VolkerK và Lukas Lalinsky cả đề xuất số find_in_set của MySQL, có lẽ tốt hơn là like cho những gì bạn muốn làm. Tuy nhiên, khuyến cáo sau đây về việc chuẩn hóa cơ sở dữ liệu của bạn vẫn được áp dụng.

Tuy nhiên, bạn không nên lưu trữ nhiều giá trị trong một trường cơ sở dữ liệu duy nhất. Thay vào đó, hãy xem xét sử dụng hai bảng:

course_data: 
    user_id 

course_days: 
    user_id 
    day_number 

Sau đó, bạn sẽ có các dữ liệu sau:

course_data: 
    user_id 
    405 

course_days 
    user_id day_number 
    405  1 
    405  3 
    405  5 

Sau đó bạn có thể truy vấn một cách chính xác sơ đồ này. Ví dụ:

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 
    ) 

(hoặc, mà nên được gần; Tôi không chính xác chắc chắn những gì bạn đang cố gắng để thực hiện hoặc những gì còn lại của giản đồ của bạn trông như thế nào, vì vậy đây là một đoán tốt nhất) .

+0

Cảm ơn. Bạn đúng về việc thay đổi cấu trúc. Tôi đã đi trước và làm như vậy. Cảm ơn bạn. – Dodinas

+0

"vì vậy đây là một dự đoán tốt nhất": một ý tưởng khác (hy vọng khả thi) là sử dụng truy vấn con không tồn tại như được mô tả tại http://dev.mysql.com/doc/refman/5.1/en/exists-and-not- exist-subqueries.html thay vì 'x NOT IN (truy vấn phụ)' – VolkerK

+0

% như% sẽ cung cấp 11 cho tìm kiếm 1, vì vậy nó không thực sự phù hợp, vì vậy câu trả lời này không thực sự áp dụng cho câu hỏi gốc. Câu trả lời từ theomega dường như áp dụng nhiều hơn cho OP. – Tarquin

14

Xóa báo giá trong tuyên bố IN. Cú pháp là:

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

và không phải là bạn sử dụng nó

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

Cũng thấy documentation vào IN, có nhiều ví dụ.

+0

Thực ra, xin lỗi, tôi cần làm rõ một số. Tôi đang làm điều gì sai ở đây. Nếu tôi sử dụng: WHERE days IN (1), nó sẽ loại bỏ nó đúng cách và trả lại kết quả trống. Nhưng nếu tôi sử dụng: WHERE days IN (3), nó không trả về một truy vấn trống. Tôi nghĩ rằng nó nên loại bỏ các truy vấn vì '3' là trong truy vấn? Bất kỳ ý tưởng? – Dodinas

+0

Tôi đoán điều này là bởi vì nó chuyển đổi "1,3,5" thành một int (dừng tại dấu phẩy), và sau đó thấy rằng nó phù hợp. – Yuliy

+0

Không chắc chắn tại sao đây không phải là câu trả lời được chấp nhận cho kịch bản được đưa ra trong bài đăng gốc - mặc dù tôi chấp nhận rằng câu trả lời được chấp nhận cung cấp lời khuyên về việc sửa các thói quen viết mã xấu. – Tarquin

0

ngày không chứa danh sách các chuỗi. Nó chứa một chuỗi duy nhất. Có phải chuỗi "1,3,5" bên trong một trong các chuỗi trong {'1'} không? Rõ ràng câu trả lời là không. Hoặc ngày Refactor vào một bảng khác nhau, hoặc được chuẩn bị để làm nhiều chuỗi thao tác

2

Nếu tôi hiểu câu hỏi của bạn đúng, bạn muốn nội dung của trường varchar được coi là danh sách được phân cách bằng dấu phẩy và kiểm tra xem danh sách này có chứa một giá trị nhất định hay không. Bạn cần có chức năng find_in_set(str, strlist).
Nhưng hãy nhớ rằng MySQL không thể sử dụng chỉ mục trong trường hợp đó và truy vấn của bạn sẽ luôn cần quét toàn bộ bảng. Nó có thể tốt hơn là không lưu trữ dữ liệu có cấu trúc (và chạy so sánh trên các phần tử đơn lẻ) trong một cột duy nhất nhưng để sử dụng một bảng khác và JOIN như đã được đề xuất trong các phản hồi khác.

5

Tôi nghĩ rằng truy vấn mà bạn muốn là:

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 

Nhưng bạn nên nghiêm túc xem xét việc bình thường hóa cơ sở dữ liệu, vì vậy mà mỗi ngày có nó hàng riêng.