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 BY
mệnh đề; - được sử dụng với
GROUP BY
tổ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 BY
mệ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.