I was trying to use the query below to update the ORDERS
table by making the O_TOTALPRICE
column up-to-date when the LINEITEM
table is modified. And I was using a standard TPC-H database.
UPDATE ORDERS O, LINEITEM L
SET
O.O_TOTALPRICE = SUM(L.L_EXTENDEDPRICE * (1 - L.L_DISCOUNT/100) * (1 + L.L_TAX/100))
WHERE
L.L_ORDERKEY = O.O_ORDERKEY;
However, this results in 1111 - Invalid use of group function
.
The operation is like this:
-----------------LINEITEM---------------- ---------ORDERS---------
L_ORDERKEY L_EXTPRICE L_DISCOUNT L_TAX O_ORDERKEY O_TOTALPRICE
========== ========== ========== ===== ========== ============
1 12.99 20 8.5 ┬ 1 <TO CALC>
1 8.99 30 11 ┘
2 99.99 10 10 ┬ 2 <TO CALC>
2 49.99 0 8.5 ┤
2 3.99 50 14.7 ┘
Since there are multiple rows in LINEITEM
corresponding to the record in ORDERS
, I tried to add GROUP BY L.L_ORDERKEY
, but that just came to a syntax error.
Is this possible to accomplish in the UPDATE
statement, or does it have to be split to multiple statements? Thanks!!
2 Answers 2
Assumptions:
L.L_EXTENDEDPRICE
should beL.L_EXTPRICE
L_DISCOUNT
andL_TAX
are percentages, in which case the values stored inLINEITEM
need to first be divided by 100.0 before performing calculations
Some sample data:
drop table if exists LINEITEM;
drop table if exists ORDERS;
create table ORDERS
(O_ORDERKEY int
,O_TOTALPRICE decimal(10,2));
insert into ORDERS values
(1,0.0),
(2,0.0);
create table LINEITEM
(L_ORDERKEY int
,L_EXTPRICE decimal(10,2)
,L_DISCOUNT decimal(10,2)
,L_TAX decimal(10,2));
insert into LINEITEM values
(1,12.99,20, 8.5),
(1, 8.99,30,11),
(2,99.99,10,10),
(2,49.99, 0, 8.5),
(2, 3.99,50,14.7);
Contents of ORDERS
before the update:
select * from ORDERS;
O_ORDERKEY O_TOTALPRICE
---------- ------------
1 0.00
2 0.00
Proposed update statement:
update ORDERS O
set O.O_TOTALPRICE = (select sum(L.L_EXTPRICE * (1 - L.L_DISCOUNT/100.0) * (1 + L.L_TAX/100.0))
from LINEITEM L
where L.L_ORDERKEY = O.O_ORDERKEY);
Contents of ORDERS
after the update:
select * from ORDERS;
O_ORDERKEY O_TOTALPRICE
---------- ------------
1 18.26
2 155.52
Here's a rextester fiddle of the above.
-
Sorry I made a mistake when making the boxed chart. But hopefully it does not affect the main part of the
UPDATE
statement.jackxujh– jackxujh2017年11月29日 20:21:04 +00:00Commented Nov 29, 2017 at 20:21 -
not sure I understand your comment; if you've made a typo in the question then I'd suggest you update the question otherwise ... have you tried the proposed update and if so, what happened ... error? wrong answer? correct answer?markp-fuso– markp-fuso2017年11月29日 20:35:17 +00:00Commented Nov 29, 2017 at 20:35
-
I am sorry for the trouble! I am outside now (using the app on my phone), and I will try the proposed answers once I am back to my computer.jackxujh– jackxujh2017年11月29日 20:40:06 +00:00Commented Nov 29, 2017 at 20:40
-
Yes, this does work! I am very sorry it took me so long to get back to this, and I had you wait for the follow-up this long!jackxujh– jackxujh2017年12月10日 11:29:36 +00:00Commented Dec 10, 2017 at 11:29
-
no problem, glad I could helpmarkp-fuso– markp-fuso2017年12月10日 14:11:00 +00:00Commented Dec 10, 2017 at 14:11
UPDATE ORDERS
JOIN
( SELECT L_ORDERKEY,
SUM(L.L_EXTENDEDPRICE * (1 - L_DISCOUNT) * (1 + L_TAX)) AS ep
FROM LINEITEM
GROUP BY L_ORDERKEY
) AS j ON j.L_ORDERKEY = ORDERS.O_ORDERKEY
SET ORDERS.O_TOTALPRICE = j.ep;
If that fails, try this syntax:
UPDATE ORDERS
SET O_TOTALPRICE =
( SELECT SUM(L.L_EXTENDEDPRICE * (1 - L_DISCOUNT) * (1 + L_TAX))
FROM LINEITEM
WHERE L_ORDERKEY = ORDERS.O_ORDERKEY
)
-
Will join operation take more time?jackxujh– jackxujh2017年11月29日 20:28:10 +00:00Commented Nov 29, 2017 at 20:28
-
The
JOIN
will probably be faster, since it is computing all the new values at once. The subquery with theSUM
is probably slower.Rick James– Rick James2017年11月29日 20:30:13 +00:00Commented Nov 29, 2017 at 20:30 -
@jackxujh: compare query plans and execution metrics to know for sure which is slower/faster (assuming there is in fact a difference); a lot will depend on how the query engine decides to parse/compile the querymarkp-fuso– markp-fuso2017年11月29日 20:36:25 +00:00Commented Nov 29, 2017 at 20:36
-
Both the
ORDERS
andLINETIEM
tables actually have many more columns, and foreign keys. AndORDERS
is referenced byLINEITEM
. ( also a TPC-H thing) But theO_TOTALPRICE
is not not referenced nor a prime key. Considering all these, will theJOIN
still faster?jackxujh– jackxujh2017年11月29日 20:36:41 +00:00Commented Nov 29, 2017 at 20:36 -
@markp - The query plan won't show the whole picture. Table size and bulkiness of the columns play a factor.Rick James– Rick James2017年11月29日 21:01:39 +00:00Commented Nov 29, 2017 at 21:01
L_
is, since it is preceded byL.
.ORDERS
look like after a successful updateL_
is in the TPC-H DDL file, and I didn't change it. I do agree theL.
is so extra, though.1111
error message is shown in the question, I wonder why mariaDB didn't tell me which line had the error. In fact, I was using thisUPDATE
statement in a stored procedure, and the creation is fine,. But when executing the procedure, I get the1111
error with no indication which part is wrong..