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

CẬP NHẬT BẢNG CÓ SUM

Trình kích hoạt có lẽ bạn muốn bạn muốn. Tuy nhiên, làm cho điều này hoạt động đúng cách và hiệu quả sẽ rất xấu. Có lẽ tốt hơn là không nên lưu trữ số dư trong mỗi hàng nếu bạn thường xuyên chèn các hàng vào những ngày trước đó; thay vào đó, hãy sử dụng truy vấn hoặc chế độ xem để tìm số dư. Để tìm số dư vào một ngày cụ thể, hãy nối số dư đó với các hàng cho các ngày trước đó và tính tổng số tiền gửi ròng, nhóm theo ID giao dịch hiện tại:

CREATE VIEW pettybalance
  AS SELECT SUM(older.pc_in - older.pc_out) AS balance, 
            current.pc_id AS pc_id,  -- foreign key
            current.pc_date AS `date`
       FROM pettycash AS current
         JOIN pettycash AS older
           ON current.pc_date > older.pc_date 
              OR (current.pc_date = older.pc_date AND current.pc_id >= older.pc_id)
       GROUP BY current.pc_id
;

Tôi cũng hạn chế older.pc_id nhỏ hơn current.pc_id để khắc phục sự không rõ ràng liên quan đến lược đồ và phép tính số dư. Kể từ pc_date không phải là duy nhất, bạn có thể có nhiều giao dịch trong một ngày nhất định. Nếu đúng như vậy, số dư cho mỗi giao dịch phải là bao nhiêu? Ở đây, chúng tôi giả định rằng một giao dịch có ID lớn hơn xảy ra sau một giao dịch có ID nhỏ hơn nhưng có cùng ngày. Chính thức hơn, chúng tôi sử dụng đặt hàng

Lưu ý rằng trong chế độ xem, chúng tôi sử dụng thứ tự ≥ dựa trên>:

Sau khi cố gắng làm cho các trình kích hoạt hoạt động bình thường, tôi khuyên bạn không nên thử. Do bảng nội bộ hoặc khóa hàng khi chèn / cập nhật, bạn phải di chuyển cột số dư sang bảng mới, mặc dù điều này không quá phức tạp (đổi tên pettycash tới pettytransactions , tạo một pettybalance (balance, pc_id) bảng và tạo một dạng xem có tên pettycash hơn tham gia pettytransactionspettybalance trên pc_id ). Vấn đề chính là các cơ quan trình kích hoạt thực thi một lần cho mỗi hàng được tạo hoặc cập nhật, điều này sẽ khiến chúng cực kỳ kém hiệu quả. Một giải pháp thay thế là tạo thủ tục được lưu trữ để cập nhật các cột mà bạn có thể gọi sau khi chèn hoặc cập nhật. Một thủ tục có hiệu suất cao hơn khi lấy số dư hơn là một khung nhìn, nhưng dễ hỏng hơn vì các lập trình viên phải cập nhật số dư, thay vì để cơ sở dữ liệu xử lý nó. Sử dụng chế độ xem là thiết kế gọn gàng hơn.

DROP PROCEDURE IF EXISTS update_balance;
delimiter ;;
CREATE PROCEDURE update_balance (since DATETIME)
BEGIN
    DECLARE sincebal DECIMAL(10,2);
    SET sincebal = (
          SELECT pc_bal 
            FROM pettycash AS pc 
            WHERE pc.pc_date < since
            ORDER BY pc.pc_date DESC, pc.pc_id DESC LIMIT 1
        );
    IF ISNULL(sincebal) THEN
      SET sincebal=0.0;
    END IF;
    UPDATE pettycash AS pc
      SET pc_bal=(
        SELECT sincebal+SUM(net) 
          FROM (
            SELECT pc_id, pc_in - pc_out AS net, pc_date
              FROM pettycash
              WHERE since <= pc_date 
          ) AS older
          WHERE pc.pc_date > older.pc_date
             OR (pc.pc_date = older.pc_date 
                 AND pc.pc_id >= older.pc_id)
      ) WHERE pc.pc_date >= since;
END;;
delimiter ;

Lạc đề

Một vấn đề với lược đồ hiện tại là việc sử dụng Float s để lưu trữ các giá trị tiền tệ. Do cách biểu diễn số dấu phẩy động, các số chính xác trong cơ số 10 (tức là không có biểu diễn thập phân lặp lại) không phải lúc nào cũng chính xác như số thực. Ví dụ:0,01 (trong cơ số 10) sẽ gần hơn với 0,009999999776482582 ... hoặc 0,0100000000000000002081668 ... khi được lưu trữ. Nó giống như cách 1/3 trong cơ sở 3 là "0,1" nhưng 0,333333 .... trong cơ sở 10. Thay vì Float , bạn nên sử dụng Decimal loại:

ALTER TABLE pettycash MODIFY pc_in DECIMAL(10,2);
ALTER TABLE pettycash MODIFY pc_out DECIMAL(10,2);

Nếu sử dụng một chế độ xem, hãy thả pettycash.pc_bal . Nếu sử dụng quy trình được lưu trữ để cập nhật pettycash.pc_bal , nó cũng nên được thay đổi.




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Cách hiển thị đối chiếu máy chủ trong MySQL

  2. Không thể tìm thấy tệp mysql-connector-java-5.1.13-bin.jar

  3. đếm giá trị mysql

  4. mysqli_connect tới máy chủ từ xa

  5. MySQL:Làm thế nào để chuyển đổi sang EAV?