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

Tổng tích lũy trên một tập hợp các hàng trong mysql

CẬP NHẬT

MySQL 8.0 giới thiệu "chức năng cửa sổ", chức năng tương đương với "chức năng cửa sổ" của SQL Server (với phân vùng và thứ tự được cung cấp bởi Transact-SQL OVER cú pháp) và "các hàm phân tích" của Oracle.

Sổ tay tham khảo MySQL 12.21 Các chức năng của cửa sổ https://dev.mysql .com / doc / refman / 8.0 / en / window-functions.html

Câu trả lời được cung cấp ở đây là một cách tiếp cận dành cho các phiên bản MySQL trước 8.0.

CÂU TRẢ LỜI GỐC

MySQL không cung cấp hàm phân tích kiểu mà bạn sẽ sử dụng để nhận "tổng tích lũy" đang chạy, giống như các hàm phân tích có sẵn trong các DBMS khác (như Oracle hoặc SQL Server.)

Tuy nhiên, có thể mô phỏng một số hàm phân tích bằng MySQL.

Có (ít nhất) hai cách tiếp cận khả thi:

Một là sử dụng truy vấn con tương quan để lấy tổng phụ. Cách tiếp cận này có thể tốn kém trên các tập hợp lớn và phức tạp nếu các vị từ trên truy vấn bên ngoài phức tạp. Nó thực sự phụ thuộc vào mức độ phức tạp của "nhiều phép nối trên nhiều bảng". (Thật không may, MySQL cũng không hỗ trợ CTE.)

Cách tiếp cận khác là sử dụng các biến người dùng MySQL, để thực hiện một số xử lý ngắt kiểm soát. "Thủ thuật" ở đây là sắp xếp các kết quả từ truy vấn của bạn (sử dụng ORDER BY) và sau đó gói truy vấn của bạn trong một truy vấn khác.

Tôi sẽ đưa ra một ví dụ về cách tiếp cận thứ hai.

Do thứ tự mà MySQL thực hiện các hoạt động, cumulative_total cột cần được tính trước giá trị từ idday từ hàng hiện tại được lưu vào các biến người dùng. Đơn giản nhất là đặt cột này đầu tiên.

Chế độ xem nội tuyến có bí danh là i (trong truy vấn bên dưới) chỉ ở đó để khởi tạo các biến người dùng, đề phòng trường hợp các biến này đã được đặt trong phiên. Nếu những giá trị đó đã được gán giá trị, chúng tôi muốn bỏ qua các giá trị hiện tại của chúng và cách dễ nhất để làm điều đó là khởi tạo chúng.

Truy vấn ban đầu của bạn được bao bọc trong dấu ngoặc đơn và được đặt một bí danh, c trong ví dụ dưới đây. Thay đổi duy nhất đối với truy vấn ban đầu của bạn là việc bổ sung mệnh đề ORDER BY, vì vậy chúng tôi có thể chắc chắn rằng chúng tôi xử lý các hàng từ truy vấn theo trình tự.

Lựa chọn bên ngoài kiểm tra xem idday giá trị từ hàng hiện tại "khớp" với hàng trước đó. Nếu có, chúng tôi thêm amount từ hàng hiện tại đến tổng phụ tích lũy. Nếu chúng không khớp, thì chúng tôi đặt lại tổng phụ tích lũy thành 0 và thêm số tiền từ hàng hiện tại (hoặc đơn giản hơn, chỉ cần chỉ định số tiền từ hàng hiện tại).

Sau khi chúng tôi thực hiện tính toán tổng tích lũy, chúng tôi lưu idday các giá trị từ hàng hiện tại thành các biến người dùng để chúng có sẵn khi chúng tôi xử lý hàng tiếp theo.

Ví dụ:

SELECT IF(@prev_id = c.id AND @prev_day = c.day
         ,@cumtotal := @cumtotal + c.amount
         ,@cumtotal := c.amount) AS cumulative_total
     , @prev_id  := c.id  AS `id`
     , @prev_day := c.day AS `day`
     , c.hr
     , c.amount AS `amount'
  FROM ( SELECT @prev_id  := NULL
              , @prev_day := NULL
              , @subtotal := 0
       ) i
  JOIN (

         select id, day, hr, amount from
         ( //multiple joins on multiple tables)a
         left join
         (//unions on multiple tables)b
         on a.id=b.id

         ORDER BY 1,2,3
       ) c

Nếu cần trả về các cột theo một thứ tự khác, với tổng tích lũy là cột cuối cùng, thì một tùy chọn là gói toàn bộ câu lệnh đó trong một tập hợp các parens và sử dụng truy vấn đó như một dạng xem nội tuyến:

SELECT d.id
     , d.day
     , d.hr
     , d.amount
     , d.cumulative_total
FROM (
       // query from above
     ) d


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Làm cách nào để chèn dữ liệu vào cơ sở dữ liệu MySQL?

  2. Ví dụ YEAR () - MySQL

  3. Tìm nạp danh sách liên kết trong cơ sở dữ liệu MySQL

  4. Cách xuất cơ sở dữ liệu bằng dòng lệnh

  5. Truy vấn được tham số hóa cho MySQL với C #