2012-11-05 31 views
5

Tôi có hai bảngParse trong MySQL sử dụng dấu phẩy như delimiter

Table1 với danh sách người dùng dấu phẩy tách

Name UserID 
abc  A,B,C,D 
def  A,B,C 

Table2

Name UserID 
abc A 
abc B 
abc C 
def A 
def B 

Tôi cần phải tìm những người sử dụng có trong table1 cho mỗi Tên nhưng không có trong bảng 2 (Sẽ không bao giờ có một ví dụ khi cặp UserID to Name xuất hiện trong bảng 2 nhưng không có trong bảng 1 dưới dạng CSV).

Sản lượng nên

Name UserID 
abc  D 
def  C 

tôi có thể làm điều này với PHP nhưng là có một cách này có thể được thực hiện thông qua một truy vấn? Tôi không chắc chắn nên bắt đầu từ đâu trong trường hợp tôi làm điều này như một truy vấn. Tôi có thể phân tích cú pháp trong MySQL bằng dấu phẩy như dấu phân cách không?

+0

'Tôi cần tìm người dùng trong bảng1 cho ** mỗi Tên ** nhưng không phải trong bảng2'. Nhưng 'D' trong bảng 1 không nằm trong ** mỗi Tên **. 'D' chỉ trong' abc'. Sau đó làm thế nào nó đến trong sản lượng mong muốn của bạn? – hims056

+0

Ý tôi là mỗi cặp UserID .. – Ank

+3

Bạn có dữ liệu không chuẩn hóa trong cơ sở dữ liệu của mình. Những gì tôi muốn khuyên bạn nên làm là chạy một kịch bản PHP để chuẩn hóa dữ liệu, và lưu kết quả vào bình thường hóa trong cơ sở dữ liệu của bạn. Bằng cách này, truy vấn cụ thể này và tất cả các truy vấn trong tương lai sẽ đơn giản hơn nhiều. Nói chung, tốt nhất là tránh các giá trị được phân cách bằng dấu phẩy được lưu trữ trong các trường cơ sở dữ liệu. Đọc thêm về bình thường hóa cơ sở dữ liệu tại đây: http://databases.about.com/od/specificproducts/a/normalization.htm –

Trả lời

3

Tôi đã cắm dữ liệu thử nghiệm của bạn vào một giản đồ thử nghiệm trong SQLFiddle và chạy truy vấn theo sau.

Đây là liên kết để SQLFiddle với các thử nghiệm và kết quả tích cực: http://sqlfiddle.com/#!2/83dfd/4/0

Dưới đây là các truy vấn:

SELECT 
COALESCE(NORMALIZED_TABLE1.NAME, TABLE2.NAME) AS NAME, 
COALESCE(NORMALIZED_TABLE1.USERID, TABLE2.USERID) AS USERID 
FROM (
    SELECT NAME, 
    SUBSTRING(
      USERID 
      FROM CASE 
       WHEN INDEX_TABLE.POS = 1 THEN 1 
       ELSE INDEX_TABLE.POS + 1 
       END 
      FOR CASE LOCATE(',', USERID, INDEX_TABLE.POS + 1) 
       WHEN 0 THEN CHARACTER_LENGTH(USERID) + 1 
       ELSE LOCATE(',', USERID, INDEX_TABLE.POS + 1) 
       END 
       - CASE 
       WHEN INDEX_TABLE.POS = 1 THEN 1 
       ELSE INDEX_TABLE.POS + 1 
       END 
    ) AS USERID 
    FROM TABLE1 
    INNER JOIN (
      SELECT @rownum:[email protected]+1 POS 
      FROM (
      SELECT 0 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 
      UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 
      UNION SELECT 7 UNION SELECT 8 UNION SELECT 9 
     ) a, (
      SELECT 0 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 
      UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 
      UNION SELECT 7 UNION SELECT 8 UNION SELECT 9 
     ) b, (
      SELECT 0 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 
      UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 
      UNION SELECT 7 UNION SELECT 8 UNION SELECT 9 
     ) c, (SELECT @rownum:=0) r 
    ) INDEX_TABLE 
    ON INDEX_TABLE.POS <= CHAR_LENGTH(TABLE1.USERID) 
    AND (
      INDEX_TABLE.POS = 1 
      OR SUBSTRING(USERID FROM INDEX_TABLE.POS FOR 1) = ',' 
    ) 
) AS NORMALIZED_TABLE1 
LEFT OUTER JOIN TABLE2 
ON NORMALIZED_TABLE1.NAME = TABLE2.NAME 
AND NORMALIZED_TABLE1.USERID = TABLE2.USERID 
WHERE TABLE2.NAME IS NULL; 

Nếu bạn có chiều rộng cột rất dài trong table1 bạn có thể cần phải mở rộng "INDEX_TABLE "truy vấn phụ. Bạn có thể sao chép và dán mã đó bằng mã tại liên kết này để làm như vậy:
http://www.experts-exchange.com/Database/MySQL/A_3573-A-MySQL-Tidbit-Quick-Numbers-Table-Generation.html

+1

kiểm tra tham gia đầy đủ bên ngoài cho dữ liệu bị thiếu từ cả hai bảng. Tôi chỉ nhận ra rằng bạn chỉ có thể mất dữ liệu từ họ. Logic truy vấn tương tự sẽ vẫn hoạt động, nhưng bạn có thể thay thế mã trên ở bên ngoài phép nối ngoài đầy đủ với phép nối ngoài bên phải –

+0

HOẶC ... bạn có thể thay thế cú pháp 'nối' và mệnh đề where hiện tại bằng 'where not exist' ...) 'khoản.Điều đó có lẽ có lẽ là cách thanh lịch nhất để đi, có thể hơi nhanh hơn. –

+0

Vì nhận ra rằng bạn không muốn mất kết quả từ cả hai bảng, nó cũng xảy ra rằng điều này sẽ đơn giản hơn nhiều và làm tốt. CHỌN TÊN, USERID TỪ table2 nơi không tồn tại ( CHỌN 0 từ table1 ĐÂU TABLE1.NAME = TABLE2.NAME AND ( TABLE1.USERID LIKE '%,' + TABLE2.USERID + '%' HOẶC TABLE1.USERID THÍCH TABLE2.USERID + ',%' HOẶC TABLE1.USERID LIKE '%,' + TABLE2.USERID ) ); –

0

Nếu bảng của bạn được cố định (bạn muốn làm việc trên các bảng đó) thì hãy thiết kế một lớp để đọc dữ liệu từ chúng thay vì trực tiếp lưu dữ liệu đã đặt từ các bảng được xác định trước đó; cho phép đối tượng của bạn xử lý dữ liệu đọc trực tiếp trên miền ứng dụng của bạn để có được khả năng truy cập toàn diện. :-D

+0

Cảm ơn bạn đã trả lời. Tôi có thể viết một kịch bản PHP để phân tích cú pháp cột người dùng. Tuy nhiên, tôi đã tạo ra một mô-đun JavaScript/PHP có một truy vấn SQL làm đầu vào và hiển thị các kết quả theo một định dạng được sắp xếp. Tôi đã tự hỏi nếu có thể có một truy vấn cho vấn đề này mà tôi có thể phù hợp với mô-đun của tôi và trực tiếp nhận được đầu ra. Tôi hy vọng nó có ý nghĩa !! – Ank

+0

:-D quá chú ý. –

Các vấn đề liên quan