2011-01-27 47 views
7

Tôi có hai bảng mà tôi đang cố gắng tham gia. Một chứa một danh sách các khách hàng, người kia là một danh sách các đơn đặt hàng. Tôi đang cố gắng xây dựng một truy vấn cho phép tôi chọn tất cả khách hàng được liệt kê trong bảng khách hàng có ít nhất một đơn hàng trong bảng đơn đặt hàng. Tuy nhiên, tôi không muốn nhận bản sao cho những khách hàng có nhiều đơn đặt hàng. Bất kỳ đề xuất làm thế nào tôi có thể thực hiện điều này?MySQL - Tham gia hai bảng không trùng lặp?

Tôi biết đây có lẽ là vấn đề phổ biến, tuy nhiên tôi không biết loại truy vấn này sẽ được gọi để tôi có thể tìm kiếm câu trả lời. Bất kỳ đề xuất sẽ được đánh giá rất cao. Cảm ơn.

+0

bạn đã thử với ** DISTINCT **? – FeRtoll

Trả lời

10

Sẽ đơn giản hơn nhiều so với bạn có thể nghĩ:

select distinct(customer_id) from orders;

Edit: Nếu bạn thực sự muốn có được các thông tin đầy đủ về khách hàng,

select * from customers where customer_id in (select distinct(customer_id) from orders);

+0

Cảm ơn, điều này có vẻ như nó sẽ mang lại cơ hội thành công tốt nhất. Vì các bảng khách hàng và đơn đặt hàng quá lớn (180 triệu bản ghi trong khách hàng, 70 triệu đơn đặt hàng) sử dụng riêng biệt, đặc biệt là đối với khách hàng, là vấn đề. – Wige

+1

Tôi không nghĩ rằng sự khác biệt là cần thiết trong truy vấn phụ - hãy kiểm tra bản EXPLAIN PLAN có và không có nó để xem có sự khác biệt nào không. –

+0

Đồng ý. Tôi vô tình sao chép/dán từ truy vấn đầu tiên. –

1
select customers.id, customers.name, count(orders.id) 
from customers 
    inner join orders on orders.customer_id = customers.Id 
group by customers.id, customers.name 
having count(orders.id) > 0 
+0

Nếu tất cả những gì bạn đang quay trở lại là customer_id và số lượng đơn đặt hàng, bạn không cần phải tham gia. 'select customer_id, count (*) từ nhóm đơn đặt hàng của customer_id' sẽ thực hiện thủ thuật. –

+0

@Michael: Tôi đã thay đổi điều đó? –

+0

Ồ, không để ý. –

0
SELECT 
    c.id, 
    c.name 
FROM 
    customer c 
    INNER JOIN order o ON o.customer_id = c.id 
GROUP BY 
    c.id, 
    c.name 
HAVING 
    COUNT(o.id) >= 1 

Không thể nhớ nếu HAVING hoặc GROUP BY đến trước.

5

Sử dụng:

SELECT c.* 
    FROM CUSTOMERS c 
WHERE EXISTS (SELECT NULL 
       FROM ORDERS o 
       WHERE o.custeromid = c.id) 

Mệnh đề IN là một sự thay thế, nhưng tồn tại hoạt động tốt hơn các bản sao vì nó trả về true trên bản sao đầu tiên vì vậy nó không xử lý toàn bộ bảng.

+0

Nó sẽ không chỉ thực hiện (rất nhiều) tốt hơn nếu có một chỉ mục trên 'o.customerid'? –

+0

@Klaus Byskov Hoffmann: Bạn sẽ phải thử nghiệm và xem, nhưng thoát khỏi trận đấu đầu tiên có vẻ tốt hơn tôi so với tất cả. Kiểu dữ liệu cũng có thể đóng vai trò trong đó. –

+0

Vâng, tôi đồng ý rằng thoát khỏi trận đấu đầu tiên có lẽ hầu như luôn luôn tốt hơn. Tôi đã chỉ nghĩ về trường hợp xấu nhất và chỉ yêu cầu ra khỏi lợi ích lý thuyết :-) –

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