Tại sao nó không hoạt động với GROUP BY
SELECT * không thể được sử dụng với GROUP BY; nó là SQL không hợp lệ. GROUP BY không chọn các hàng trong bảng. Nó tạo các nhóm hàng bằng cách sử dụng các biểu thức được cung cấp, sau đó từ mỗi nhóm, nó tạo một bản ghi mới và tính toán từng cột của bản ghi mới này bằng cách sử dụng các giá trị có trong biểu thức.
Các cột xuất hiện trong SELECT mệnh đề phải đáp ứng một trong các quy tắc sau:
- cũng xuất hiện trong
GROUP BYmệnh đề; - được sử dụng với
GROUP BYtổng hợp các chức năng ; - phụ thuộc vào chức năng của các cột xuất hiện trong
GROUP BYmệnh đề.
Trong khi * là một lối tắt cho tất cả các tên cột của (các) bảng được truy vấn sử dụng, chỉ dành cho truy vấn của bạn user cột đáp ứng một trong các yêu cầu trên.
Trước phiên bản 5.7.5
MySQL không triển khai quy tắc thứ ba ở trên. Nó được sử dụng để chấp nhận các truy vấn có trong SELECT các cột mệnh đề không theo sau bất kỳ cột nào trong GROUP BY các yêu cầu. Giá trị được trả về bởi truy vấn cho các cột như vậy là không xác định
.
Kể từ phiên bản 5.7.5, MySQL từ chối GROUP BY các truy vấn đáp ứng các yêu cầu.
Giải pháp
Dù bằng cách nào, giải pháp cho vấn đề của bạn không liên quan đến GROUP BY . Nó có thể được thực hiện dễ dàng bằng cách sử dụng LEFT JOIN với các điều kiện chính xác:
SELECT lc.*
FROM comments lc # 'lc' from 'last comment'
LEFT JOIN comments nc # 'nc' from 'newer comment'
ON lc.user = nc.user # both comments belong to the same user
AND lc.id < nc.id # 'nc' is newer than 'lc'
WHERE nc.id IS NULL # there is no 'newer comment'
ORDER BY lc.id DESC
LIMIT 10
Cách hoạt động
Nó tham gia vào bảng comments , bí danh là lc ("lc" từ "nhận xét cuối cùng" của người dùng) so với chính nó, bí danh là nc ("nc" từ "bình luận mới hơn"). Mệnh đề kết hợp khớp với từng mục nhập của lc với tất cả các mục nhập của nc thuộc về cùng một người dùng (lc.user = nc.user ) và mới hơn (lc.id < nc.id; Tôi giả định rằng các ID được chỉ định tuần tự và các nhận xét mới hơn có giá trị lớn hơn cho id ).
Việc sử dụng LEFT JOIN đảm bảo rằng mọi hàng của lc xuất hiện trong kết quả của phép nối, ngay cả khi không tìm thấy hàng phù hợp nào trong nc (vì không có bình luận mới hơn của cùng một người dùng). Trong trường hợp này, NULL được sử dụng thay cho các trường của nc . WHERE mệnh đề giữ trong kết quả cuối cùng chỉ đặt các hàng có NULL trong nc.id; điều này có nghĩa là trong lc phần chúng chứa nhận xét gần đây nhất của mỗi người dùng.
SELECT mệnh đề chứa tất cả các trường của lc (của nc đều là NULL , dù sao). ORDER BY mệnh đề có thể được sử dụng để sắp xếp tập kết quả. ORDER BY lc.id DESC đặt các nhận xét gần đây nhất lên đầu tiên và LIMIT mệnh đề giữ kết quả được đặt ở kích thước phù hợp.