2012-07-10 51 views
5

Tôi gặp sự cố khi triển khai mô-đun trong đó một project có thể thuộc về nhiều categories. Ví dụ: project "PHP Programmer" thuộc về các loại: Lập trình, PHP.MySQL LEFT JOIN kết quả trùng lặp

Giả sử các truy vấn sau (chọn dự án thuộc loại 1,3,11):

SELECT projects.* FROM projects 
    LEFT JOIN pojects_category on projects.id = pojects_category.project_id 
    WHERE pojects_category.category_id IN (1,3,11) and projects.id='94'` 

tôi nhận được một dự án tương tự trở lại hai lần, bởi vì có trận đấu ở các bảng cho project_id = 94

bảng projects_category schema:

CREATE TABLE IF NOT EXISTS `pojects_category` (
    `project_id` int(10) NOT NULL, 
    `category_id` int(10) NOT NULL, 
    KEY `category_id` (`category_id`), 
    KEY `project_id` (`project_id`) 
) ENGINE=MyISAM DEFAULT CHARSET=utf8; 


INSERT INTO `pojects_category` (`project_id`, `category_id`) VALUES 
(94, 3), 
(94, 1); 

Tôi có thiếu gì đó không?

Giải pháp: sử dụng GROUP BY hoặc DISTINCT

+1

Nếu bạn chỉ muốn một trong mỗi dự án, hãy thêm 'GROUP BY project_id' vào truy vấn của bạn – mariusnn

+0

@mariusnn cảm ơn bạn, nó hoạt động! – technology

+0

Không sử dụng nhóm theo, xem giải thích của tôi – Sebas

Trả lời

8

Không, điều này là tốt. Đây chỉ là một trong những trường hợp hiếm hoi khi bạn muốn sử dụng từ khóa DISTINCT để xóa các từ khóa trùng lặp.

Trong trường hợp này, điều này được chứng minh bởi thực tế rằng logic của truy vấn là chính xác, mặc dù nó trả về nhiều hàng. Nhiều lần người ta có thể thấy việc sử dụng DISTINCT khi thực sự logic của truy vấn là sai.

Side-note:

  • bất kỳ bộ lọc trên một tài liệu tham khảo bảng bạn đang sử dụng trong các WHERE khoản khác ngoài IS NULL/IS NOT NULL sẽ thực hiện bất kỳ LEFT JOIN trên cùng một lượt bảng tham chiếu này để một INNER JOIN, như đối với resultset thức hành vi. (Thấy điều này: https://stackoverflow.com/a/15483895/1291428)
  • anh nên không sử dụng GROUP BY để mô phỏng ảnh hưởng của DISTINCT, cho 2 lý do:

    1/Đây chỉ là không phải là mục đích. Một trong những hiệu ứng của GROUP BY là loại bỏ các bản sao, nhưng mục đích chính của nó là nhóm các hàng theo một bộ tiêu chí nhất định, để áp dụng một số tính toán/hoạt động phân tích trên chúng.

    2/GROUP BY cũng ORDER BY kết quả (trong mysql), điều này không nhất thiết là điều bạn muốn và trong trường hợp đó làm chậm quá trình thực thi. Xin vui lòng, chỉ cần đảm bảo sử dụng thích hợp những gì các công cụ đang cung cấp, đó là luôn luôn tốt hơn từ quan điểm về khả năng tương thích về phía trước. (dự đoán rằng những gì bạn bao gồm như được cấp thực sự là không)

liên quan.

+0

tốt, tôi không biết rằng ... tôi đã từng nhóm là một từ đồng nghĩa cho DISTINCT. Cảm ơn, bây giờ tôi đang sử dụng riêng biệt và nó hoạt động tuyệt vời :) – technology

+0

Xe tăng để làm cho một điểm rõ ràng về DISTINCT và GROUP BY – mariusnn

0

Bạn cũng có thể viết lại này như một "IN" để có được xung quanh bản sao:

SELECT projects.* 
FROM projects  
where projects.id in (select project_id 
         from projects_category 
         WHERE pojects_category.category_id IN (1,3,11) 
        ) and 
     projects.id='94' 

Các "trong" ngăn chặn bản sao từ hình thành khi bạn đang sử dụng tham gia cho các hồ sơ lọc.