Как я могу выполнить расчет в автоматически заполненной таблице, - PullRequest
0 голосов
/ 01 августа 2020

Кажется, это основной c вопрос, но я не могу его понять

У меня есть 2 таблицы: table_a и table_b

SELECT * FROM `table_a`
+----+--------+----------+
| id | a_item | a_values |
+----+--------+----------+
|  1 |      1 |        5 |
|  2 |      1 |        5 |
+----+--------+----------+
SELECT * FROM `table_b`;
+--------+-------+
| a_item | total |
+--------+-------+
|      1 |    10 |
+--------+-------+
# NOTE: total is TEN  

Как видно, я использую триггер для SUM (a_values) из table_a и сохраняю результат в table_b. Я использую триггер:

CREATE TRIGGER totaling
    AFTER INSERT ON table_a
    FOR EACH ROW
    BEGIN
        INSERT INTO table_b(a_item, total)
        SELECT a_item, SUM(a_values) FROM table_a
        GROUP by a_item
        ON DUPLICATE KEY UPDATE
        total = VALUES(total);
    END

Теперь скажем, я обновляю table_b:

UPDATE table_b
    SET total = total - 5
    WHERE a_item = 1

# NOTE: I'm subtracting FIVE from previous total which was TEN

, и результат в столбце table_b total равен 5, что и ожидается.

SELECT * FROM `table_b`
+--------+-------+
| a_item | total |
+--------+-------+
|      1 |     5 |
+--------+-------+

До этого момента все работает соответственно. Однако, когда я делаю вставку на table_a, вычисления прекращаются. например:

INSERT INTO table_a(a_item, a_values) 
    VALUES
    (1, 5);
SELECT * FROM `table_b`;
+--------+-------+
| a_item | total |
+--------+-------+
|      1 |    15 |
+--------+-------+
# NOTE: see how the total has changed from FIVE to FIFTEEN, my expected result is TEN

Я мог бы исправить эту проблему, напрямую обновив table_a, тогда триггер вставки будет только SUM с его существующими значениями, которые дадут мне ожидаемый результат.

вопрос в том, есть ли способ, при котором я мог бы получить желаемый результат, не манипулируя table_a, а только манипулируя table_b, или мне нужно изменить триггер вставки?

спасибо.

Ответы [ 4 ]

1 голос
/ 01 августа 2020

Считайте, что сумма вообще не материализуется. Вместо этого используйте представление, которое предоставляет сумму:

DROP TABLE table_b;

CREATE VIEW table_b
AS
SELECT a_item,
       sum(item_values) total
       FROM table_a
       GROUP BY a_item;

Тогда нет необходимости в каком-либо триггере, и суммы всегда будут точными и текущими. Постоянство поддерживается постоянно.

1 голос
/ 02 августа 2020

Вы хотите TABLE table_b или VIEW table_b? У вас не может быть и того, и другого.

A TABLE - это набор данных, находящихся на диске. A VIEW не «материализуется» (по крайней мере, не в MySQL). Это просто синтаксис c сахар для чтения данных в базовых таблицах. Следовательно, VIEW может только отражает то, что в настоящее время в базовой таблице.

Вы читаете a VIEW таким же образом вы читаете TABLE, а именно SELECT.

Когда вы добавляете строки в таблицу, они сразу появляются в представлении. Сумма немедленно пересчитывается, когда вы читаете представление.

OK, «Некоторые представления можно обновлять, и ссылки на них можно использовать для указания таблиц, которые должны быть обновлены в операторах изменения данных. То есть вы можете использовать их в такие операторы, как UPDATE, DELETE или INSERT для обновления содержимого базовой таблицы ». (цитируя руководство). Но не делай этого. По крайней мере, до тех пор, пока вы не научитесь лучше обращаться с таблицами и необновляемыми представлениями.

0 голосов
/ 02 августа 2020

Мое решение проблемы заключалось в использовании прямого запроса на table_b. вместо суммирования и группировки из table_a, в котором использовался триггер, была использована процедура для вставки в обе таблицы

Она вставила / обновила table_b сама по себе:

INSERT INTO table_b(a_item, total)
    SELECT a_item, total + @var FROM table_b WHERE a_item = @var2
    GROUP BY a_item
    ON DUPLICATE KEY UPDATE
    total = VALUES(total);
# NOTE: the arithmetic operator doesn't have to be an addition.
# NOTE: @var is used as in a broad sense(not necessary as a MySQL variable).

Надежда Я ясно дал понять, и кто-то считает этот ответ полезным. ура :)

0 голосов
/ 01 августа 2020

Я думаю, что вам нужен триггер, чтобы поддерживать сумму в b, а не сбрасывать ее. Это будет:

CREATE TRIGGER totaling
AFTER INSERT ON table_a
FOR EACH ROW
BEGIN
    INSERT INTO table_b (a_item, total)
        VALUES (new.a_item, new.total)
        ON DUPLICATE KEY UPDATE total = total + VALUES(total);
END;

Возможно, вам также понадобится триггер UPDATE.

...