Mysql
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Mysql

MYSQL - Thứ tự theo Id Trong Thứ tự DESC, Nhóm theo X

Bạn đã hiểu sai cách GROUP BY hoạt động trong SQL, do một tính năng của MySQL. Trong SQL tiêu chuẩn, mọi cột không tổng hợp trong câu lệnh SELECT PHẢI nằm trong mệnh đề GROUP BY (có một ngoại lệ đối với các cột có giá trị phụ thuộc 100% vào một cột đã có trong mệnh đề GROUP BY, mặc dù một số phiên bản SQL hỗ trợ miễn trừ điều này) .

MySQL không thực thi điều này theo mặc định, nhưng giá trị hàng nào được sử dụng cho các cột đó không được xác định. Mặc dù bạn có thể nhận được thứ bạn muốn, nhưng bạn cũng có thể không. Và ngay cả khi bạn làm vậy vẫn có khả năng thay đổi trong tương lai.

Thứ tự độc lập với GROUP BY thông thường, mặc dù nếu bạn không chỉ định mệnh đề ORDER thì kết quả sẽ được sắp xếp dựa trên những gì được yêu cầu để thực hiện GROUP GROUP BY thì sau đó MySQL sẽ không bận tâm sắp xếp lại các bản ghi trừ khi bạn yêu cầu cụ thể nó với mệnh đề ORDER BY).

Vì vậy, với dữ liệu hiện tại của bạn, nhóm theo ads_post_id, giá trị của id được trả về có thể là 22, 23, 24, 104, 250, 253 hoặc 767. MySQL nào chọn để sử dụng không được xác định.

Với việc sửa chữa dữ liệu hiện tại của bạn, điều này là không đáng kể vì bạn chỉ có thể lấy được id MAX:-

SELECT ads_post_id, MAX(id) 
FROM fb_ads 
GROUP BY ads_post_id 
LIMIT 6

MAX sẽ trả về 1 hàng cho mỗi giá trị được GROUPed.

Vấn đề bình thường là mọi người muốn một cột khác cho hàng đó. Ví dụ:giả sử mỗi hàng trong dữ liệu mẫu của bạn cũng có địa chỉ IP và bạn muốn có địa chỉ IP tương đương với id cao nhất cho ads_post_id:-

id   | ads_post_id         ip_address
---------------------------------------------------------------------------
22   | 983314845117571     192.168.0.0
23   | 983314845117571     192.168.0.5
24   | 983314845117571     192.168.0.7    
104  | 983314845117571     192.168.0.0
250  | 983314845117571     192.168.0.4
253  | 983314845117571     192.168.0.6
767  | 983314845117571     192.168.0.1     
---------------------------------------------------------------------------

Trong trường hợp này, bạn không thể chỉ sử dụng MAX. Ví dụ:nếu bạn đã thử:-

SELECT ads_post_id, MAX(id), MAX(ip_address) 
FROM fb_ads 
GROUP BY ads_post_id 
LIMIT 6

Bạn sẽ nhận được dữ liệu sau được trả về

id   | ads_post_id         ip_address
---------------------------------------------------------------------------
767  | 983314845117571     192.168.0.7     
---------------------------------------------------------------------------

Nếu bạn đã thử các cách sau trong hầu hết các phiên bản SQL, bạn sẽ gặp lỗi. Trong MySQL với cài đặt mặc định, bạn sẽ nhận được một kết quả, nhưng địa chỉ IP nào được trả về không được xác định (và thực tế là ngẫu nhiên).

SELECT ads_post_id, MAX(id), ip_address 
FROM fb_ads 
GROUP BY ads_post_id 
LIMIT 6

Các giải pháp cho điều này là lấy id tối đa cho mỗi ads_post_id trong một truy vấn phụ và sau đó kết hợp nó trở lại bảng để nhận phần còn lại của các giá trị:-

SELECT a.ads_post_id,
        a.id,
        a.ip_address
FROM fb_ads a
INNER JOIN
(
    SELECT ads_post_id, MAX(id) AS max_id 
    FROM fb_ads 
    GROUP BY ads_post_id 
) sub0
ON a.ads_post_id = sub0.ads_post_id
AND a.id = sub0.max_id

Một thay thế là (ab) sử dụng hàm tổng hợp GROUP_CONCAT. GROUP_CONCAT sẽ trả lại tất cả các giá trị được nối với nhau thành 1 trường, mỗi giá trị được phân tách bằng dấu, (theo mặc định). Bạn có thể thêm mệnh đề ORDER BY để buộc thứ tự chúng được nối với nhau. Bạn có thể sử dụng SUBSTRING_INDEX để trả lại mọi thứ cho đến dấu phẩy đầu tiên.

Điều này có thể hữu ích cho dữ liệu đơn giản, nhưng sẽ trở thành vấn đề với dữ liệu văn bản hoặc các trường tối đa là NULL.

SELECT a.ads_post_id,
        SUBSTRING_INDEX(GROUP_CONCAT(id ORDER BY id DESC), ',', 1),
        SUBSTRING_INDEX(GROUP_CONCAT(ip_address ORDER BY id DESC), ',', 1)
FROM fb_ads 
GROUP BY ads_post_id 


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. PHP strtotime ():ngày hiển thị '1970-01-01' sau khi chuyển đổi

  2. MySQL Chọn nhóm bản ghi dựa trên dấu thời gian mới nhất

  3. truy vấn mysql cho danh sách được liên kết

  4. Mysql Từ vấn đề enum đến tinyint

  5. Chèn SQL trong ADOdb và bảo mật trang web chung