Mysql
 sql >> Teknologi Basis Data >  >> RDS >> Mysql

PERBARUI TABEL DENGAN SUM

Pemicu mungkin ingin Anda inginkan. Namun, membuat ini berfungsi dengan baik dan efisien akan buruk. Mungkin lebih baik untuk tidak menyimpan saldo di setiap baris jika Anda akan terlalu sering memasukkan baris pada tanggal sebelumnya; sebagai gantinya, gunakan kueri atau tampilan untuk menemukan keseimbangan. Untuk menemukan saldo pada tanggal tertentu, gabungkan dengan baris untuk tanggal sebelumnya dan jumlahkan setoran bersih, dengan mengelompokkan berdasarkan ID transaksi saat ini:

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
;

Saya juga membatasi older.pc_id menjadi kurang dari current.pc_id untuk memperbaiki ambiguitas yang berkaitan dengan skema dan perhitungan saldo. Sejak pc_date tidak unik, Anda dapat memiliki beberapa transaksi untuk tanggal tertentu. Jika demikian, berapa seharusnya saldo untuk setiap transaksi? Di sini kita berasumsi bahwa transaksi dengan ID yang lebih besar terjadi setelah transaksi dengan ID yang lebih kecil tetapi memiliki tanggal yang sama. Lebih formal, kami menggunakan pemesanan

Perhatikan bahwa dalam tampilan, kami menggunakan urutan berdasarkan>:

Setelah mencoba membuat pemicu berfungsi dengan baik, saya akan merekomendasikan untuk tidak mencoba. Karena tabel atau baris internal terkunci saat memasukkan/memperbarui, Anda harus memindahkan kolom saldo ke tabel baru, meskipun ini tidak terlalu memberatkan (ganti nama pettycash ke pettytransactions , buat pettybalance (balance, pc_id) tabel, dan buat tampilan bernama pettycash daripada bergabung dengan pettytransactions dan pettybalance di pc_id ). Masalah utamanya adalah badan pemicu dieksekusi sekali untuk setiap baris yang dibuat atau diperbarui, yang akan menyebabkannya menjadi sangat tidak efisien. Alternatifnya adalah dengan membuat prosedur tersimpan untuk memperbarui kolom, yang dapat Anda panggil setelah memasukkan atau memperbarui. Prosedur lebih berkinerja ketika mendapatkan saldo daripada tampilan, tetapi lebih rapuh karena terserah programmer untuk memperbarui saldo, daripada membiarkan database menanganinya. Menggunakan tampilan adalah desain yang lebih bersih.

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 ;

Di luar topik

Masalah dengan skema saat ini adalah penggunaan Float s untuk menyimpan nilai moneter. Karena bagaimana angka floating point direpresentasikan, angka yang tepat di basis 10 (yaitu tidak memiliki representasi desimal berulang) tidak selalu tepat sebagai float. Misalnya, 0,01 (dalam basis 10) akan lebih dekat ke 0,09999999776482582... atau 0,0100000000000000002081668... saat disimpan. Ini agak seperti bagaimana 1/3 di basis 3 adalah "0,1" tetapi 0,333333.... di basis 10. Alih-alih Float , Anda harus menggunakan Decimal ketik:

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

Jika menggunakan tampilan, jatuhkan pettycash.pc_bal . Jika menggunakan prosedur tersimpan untuk memperbarui pettycash.pc_bal , itu juga harus diubah.




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Tampilkan tabel dengan LIKE dan NOT REGEXP

  2. Pemicu MySQL saya tidak berfungsi, sintaks sederhana, tidak rumit

  3. Bagaimana saya tahu berapa banyak baris yang dikembalikan oleh kueri Perl DBI?

  4. Tidak ada data yang disediakan untuk parameter dalam pernyataan yang disiapkan

  5. mysql BUAT PENGGUNA