2011-08-29 52 views
7

Trong hệ thống của tôi, tôi có khách hàng. Khách hàng có các chương trình. Tôi muốn hiển thị một danh sách các khách hàng, hiển thị chương trình hoạt động mới nhất của họ (nếu nó tồn tại).Đặt hàng trong nhóm theo?

Do đó, chúng tôi có một cái gì đó như thế này:

SELECT * 
FROM clients AS client 
    JOIN programs AS program ON client.id=program.client_id 
GROUP BY client.id 
ORDER BY program.close_date=0 DESC, program.close_date DESC 

close_date=0 nghĩa là chương trình không được đóng lại. Vì vậy, nó sẽ đưa các chương trình không đóng đầu tiên, và sau đó các chương trình đóng gần đây nhất tiếp theo.

Sự cố là, thứ tự không hoạt động trong các nhóm. Nó chỉ là chọn một trong các chương trình một cách ngẫu nhiên. Làm cách nào để giải quyết vấn đề này?


Chỉ cần đến với điều này:

SELECT * 
FROM clients AS client 
    JOIN (SELECT * FROM programs AS program ORDER BY program.close_date=0 DESC, program.close_date DESC) AS program ON client.id=program.client_id 
GROUP BY client.id 

Mà dường như để cho kết quả chính xác. Điều này có đúng không, hoặc tôi có may mắn không? tức là, về cơ bản tôi đã sắp xếp bảng trước khi tham gia vào nó; những kết quả đó sẽ vẫn được sắp xếp khi nó tham gia, phải không?


Giải pháp: bây giờ tôi tin rằng đây là một vấn đề group-wise maximum cổ điển. Tìm kiếm điều đó nếu bạn đang mắc kẹt trên một vấn đề tương tự. Giải pháp liên quan đến việc tham gia cùng một bảng hai lần.

+3

ORDER BY trong lựa chọn phụ không có ảnh hưởng đến kết quả xác định. Nó có thể xảy ra để làm việc với MySQL, nhưng tiêu chuẩn SQL thậm chí không cho phép nó. Điểm mấu chốt là để ORDER BY client.id trong chính (truy vấn bên ngoài), sau đó bởi bất kỳ cột nào khác mà bạn muốn. Bạn có thể phải nói những điều tương tự trong các mệnh đề GROUP BY và ORDER BY; nó không tốn bất cứ điều gì để làm như vậy. –

+2

@Mark: Tôi không nghĩ rằng giải pháp thay thế của bạn (được đăng ở trên) được đảm bảo cung cấp kết quả chính xác. Sau khi một 'GROUP BY' được thực hiện trên' client.id', ["máy chủ được tự do lựa chọn bất kỳ bản ghi nào từ mỗi nhóm"] (http://dev.mysql.com/doc/refman/5.0/en/group -by-hidden-columns.html). – unutbu

+0

@ubutbu: Cảm ơn! Đó chính là điều tôi muốn biết. Tôi đã lo lắng rằng có thể là trường hợp. – mpen

Trả lời

7
SELECT c.*, p.* 
FROM clients AS c 
JOIN programs AS p 
ON  p.id = 
     (
     SELECT pi.id 
     FROM programs AS pi 
     WHERE pi.client_id = c.id 
     ORDER BY 
       pi.close_date=0 DESC, pi.close_date DESC 
     LIMIT 1 
     ) 

Thanx nên đến @Quassnoi. Xem câu trả lời của mình trong một câu hỏi tương tự (nhưng phức tạp hơn): mysql-group-by-to-display-latest-result


Nếu bạn cập nhật bảng programs và thiết lập close_date cho tất cả các hồ sơ mà nó là số không để close_date='9999-12-31', sau đó bạn ORDER BY sẽ đơn giản hơn (và toàn bộ truy vấn nhanh hơn với chỉ mục thích hợp):

 ORDER BY 
       pi.close_date DESC 
+0

Ah ... vâng, sự tham gia này có ý nghĩa hơn rất nhiều. Cảm ơn rất nhiều! – mpen

+0

Đây là câu trả lời tôi đã tìm ở khắp mọi nơi. – atomkirk

1

Hãy thử lệnh này quy định tại khoản ...

ORDER BY client.id, CASE WHEN program.close_date = 0 THEN 0 ELSE 1 END, program.close_date DESC 
+0

Tôi không thấy làm thế nào mà hoàn thành bất cứ điều gì. 'program.close_date = 0' sẽ đánh giá thành' 0' hoặc '1'. Vấn đề là tôi cần phải sắp xếp trong các nhóm, việc phân loại tổng thể (sau khi nhóm) là tốt. – mpen

+2

Cột đầu tiên được liệt kê là client.id ... sẽ giữ các nhóm của bạn với nhau. – JSR

+0

Ồ ..... bạn nên chỉ ra điều đó trong câu trả lời của bạn. Mặc dù tôi vẫn không chắc chắn 100% ý bạn là gì. Đặt 'client.id' đầu tiên sẽ thực hiện công việc sắp xếp? Tại sao điều đó tạo nên sự khác biệt? – mpen

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