Mysql
 sql >> база данни >  >> RDS >> Mysql

АКТУАЛИЗИРАНЕ НА ТАБЛИЦАТА СЪС СУМА

Задействания вероятно искате искате. Въпреки това ще бъде грозно да накарате това да работи правилно и ефективно. Вероятно е по-добре да не съхранявате баланса във всеки ред, ако ще вмъквате редове на по-ранни дати толкова често; вместо това използвайте заявки или изгледи да намерим баланса. За да намерите салдото на определена дата, съединете го с редовете за по-ранни дати и сумирайте нетния депозит, групирайки по текущия идентификатор на транзакция:

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
;

Също така ограничавам older.pc_id да бъде по-малко от current.pc_id за да се коригира неяснота, свързана със схемата и изчислението на баланса. От pc_date не е уникален, можете да имате множество транзакции за дадена дата. Ако случаят е такъв, какво трябва да бъде салдото за всяка транзакция? Тук приемаме, че транзакция с по-голям идентификатор идва след транзакция с по-малък идентификатор, но която има същата дата. По-формално, ние използваме подреждането

Обърнете внимание, че в изгледа използваме ≥ ред въз основа на>:

След като се опитате да накарате тригерите да работят правилно, ще препоръчам дори да не опитвате. Поради вътрешни блокировки на таблица или ред при вмъкване/актуализиране, трябва да преместите колоната за баланса в нова таблица, въпреки че това не е твърде обременително (преименувайте pettycash към pettytransactions , създайте нов pettybalance (balance, pc_id) таблица и създайте изглед с име pettycash отколкото се присъединява към pettytransactions и pettybalance на pc_id ). Основният проблем е, че тригерните тела се изпълняват веднъж за всеки създаден или актуализиран ред, което ще ги накара да бъдат невероятно неефективни. Алтернатива би била да създадете съхранена процедура за актуализиране на колони, които можете да извикате след вмъкване или актуализиране. Една процедура е по-ефективна, когато получава баланси, отколкото изглед, но е по-крехка, тъй като зависи от програмистите да актуализират балансите, вместо да оставят базата данни да се справи с това. Използването на изглед е по-чистият дизайн.

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 ;

Извън темата

Проблем с текущата схема е използването на Float s за съхраняване на парични стойности. Поради начина, по който се представят числата с плаваща запетая, числата, които са точни при основа 10 (т.е. нямат повтарящо се десетично представяне), не винаги са точни като числа с плаваща запетая. Например 0,01 (в база 10) ще бъде по-близо до 0,009999999776482582... или 0,0100000000000000002081668... когато се съхранява. По-скоро е като как 1/3 в основа 3 е "0,1", но 0,333333.... в основа 10. Вместо Float , трябва да използвате Decimal тип:

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

Ако използвате изглед, пуснете pettycash.pc_bal . Ако използвате съхранена процедура за актуализиране на pettycash.pc_bal , то също трябва да бъде променено.




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Facebook регистрация Connect

  2. Борба с персонализирана SQL заявка

  3. Вмъкнете часовия формат h:mm pm/am в базата данни с помощта на MYSQL

  4. предаване на идентификационен номер при щракване с помощта на ajax към php

  5. MySQL се срива (някои указатели може да са невалидни и да причинят прекратяване на изхвърлянето)