Как обновить атрибут на основе результата агрегатной функции - PullRequest
1 голос
/ 07 апреля 2019

Я новичок в MySQL. Я хочу обновить стоимость заказа таблицы, исходя из значения розничной цены и количества заказанного товара. У меня есть следующие таблицы (упрощенно для этого вопроса):

Products * * 1004

ProductID
Retail_price

Sales_orders

SalesOrdersID
Order_price //This is the derived attribute that I want to update when the below Sales_products table is updated.

Sales_products:

SalesOrdersID
ProductID
Quantity

Следующий код работает в том, что я получаю правильный Order_price, и он выводит в своей собственной таблице. Но я хочу обновить атрибут Sales_orders.Order_price, а не вызывать цену заказа в таблице.

SELECT 
    sales_product.SalesOrdersID, 
    SUM(Quantity * Retail_price) as "Total price of order"
FROM 
    sales_product
    LEFT JOIN products ON sales_product.ProductID = products.ProductID
GROUP BY sales_product.SalesOrdersID

Я также попробовал триггер, но он возвращает ошибку, когда я пытаюсь вставить новую строку в Sales_orders.

CREATE trigger find_order_price2
AFTER INSERT ON Sales_products
FOR EACH ROW

BEGIN
    DECLARE price int;
SELECT
    sales_product.SalesOrdersID, SUM(Quantity * Retail_price) INTO price
FROM
    sales_product
        LEFT JOIN
        products ON sales_product.ProductID = products.ProductID;
UPDATE sales_orders
set Order_price = price;
END;
$$
DELIMITER ;

Ошибка вернулась:

Код ошибки: 1222. Используемые операторы SELECT имеют разное количество столбцов

Надеюсь, кто-нибудь может помочь с этим?

Ответы [ 2 ]

0 голосов
/ 07 апреля 2019

Это триггер, поэтому я ожидаю, что он будет использовать new или old.

Обычно это делается постепенно:

CREATE trigger trig_sales_products_update_price
AFTER INSERT ON Sales_products
FOR EACH ROW
BEGIN
    UPDATE sales_order so JOIN
           product p
           ON p.product_id = new.product_id
        SET so.order_price = so.order_price + new.quantity * p.retail_price
        WHERE so.SalesOrderId = new.SalesOrderId
END;
$$
DELIMITER ;

Вы можете пересчитать все значение, если хотите:

CREATE trigger trig_sales_products_update_price
AFTER INSERT ON Sales_products
FOR EACH ROW
BEGIN
    UPDATE sales_order so JOIN
           (SELECT sp.SalesOrderId,
                   SUM(sp.quantity * p.retail_price) as new_total
            FROM sales_products sp
                 product p
                 ON p.product_id = sp.product_id
            WHERE sp.SalesOrderId = new.SalesOrderId
            GROUP BY sp.SalesOrderId
           ) sp
           ON so.SalesOrderId = sp.SalesOrderId
        SET so.order_price = sp.new_total
END;
$$
DELIMITER ;

Однако триггеры обычно выполняются постепенно.

Помните, что если вы сделаете это, вам также понадобятся триггеры update и delete. Вот почему эти значения проще вычислять «на лету», чем поддерживать их с помощью триггеров.

0 голосов
/ 07 апреля 2019

Следующий код запуска должен выполнить работу:

DELIMITER $$
CREATE trigger update_sales_order_price
AFTER INSERT ON Sales_products
FOR EACH ROW
BEGIN

    UPDATE Sales_orders so
    SET Order_price = (
        SELECT SUM(sp.Quantity * p.Retail_price)
        FROM Sales_products sp
        INNER JOIN Products p ON p.ProductID  = sp.ProductID 
        WHERE sp.SalesOrdersID = so.SalesOrdersID
    )
    WHERE SalesOrdersID = NEW.SalesOrdersID;

END;
$$
DELIMITER;

Демонстрация на DB Fiddle :

Рассмотрим следующую раскладку:

Продукты:

| ProductID | retail_price |
| --------- | ------------ |
| 1         | 10           |
| 2         | 20           |

Sales_products:

| SalesOrdersID | ProductID | Quantity |
| ------------- | --------- | -------- |
| 1             | 1         | 10       |

Sales_orders:

| SalesOrdersID | Order_price |
| ------------- | ----------- |
| 1             | 100         |

Теперь, с триггером на месте, мы вставляем новую запись в таблицу Sales_items, которая относится к тому же порядку продаж:

insert into Sales_products values(1, 2, 10);

После вставки вот (обновленное) содержимое таблицы Sales_orders:

| SalesOrdersID | Order_price |
| ------------- | ----------- |
| 1             | 300         |
...