Calculate column value from another column in another table - mysql

I have a table that contains the unit price and other details of each item in a store.
CREATE TABLE Item (Item_id CHAR(4), Description CHAR(40), Sizes CHAR(40), Weight REAL, Unit_price REAL, PRIMARY KEY(Item_id));
And another one that contains details of the items contained in each order.
CREATE TABLE Order_contains_items (Item_id CHAR(4), Order_no INT, Quantity_ordered INT, Ordered_price REAL, PRIMARY KEY(Item_id, Order_no), FOREIGN KEY(Order_no) REFERENCES Order(Order_no), FOREIGN KEY(Item_id) REFERENCES Item(Item_id));
Now I want to compute
Order_contains_items.Ordered_price = Item.Unit_price * Order_contains_items.Quantity_ordered WHERE Order_contains_items.Item_id = Item.Item_id
Note that I want it to be a part of the table itself and not as a different view or a query. How can I do this? I looked into triggers and other mechanisms for this but do they work for values in different tables especially with such constraints?
I tried the following trigger based on Column calculated from another column? :
CREATE TRIGGER Order_price BEFORE INSERT ON Order_contains_items
FOR EACH ROW BEGIN
SET NEW.Ordered_price = Item.Unit_price * NEW.Quantity_ordered
WHERE NEW.Item_id = Item.Item_i
END;
But it didn't seem to work

Here is how you can do that in MySQL (your question is tagged with both mysql and sql-server)
CREATE TRIGGER tg_bi_order_contains_items
BEFORE INSERT ON Order_contains_items
FOR EACH ROW
SET NEW.Ordered_price =
(
SELECT Unit_price * NEW.Quantity_ordered
FROM Item
WHERE Item_id = NEW.Item_id
LIMIT 1
);
CREATE TRIGGER tg_bu_order_contains_items
BEFORE UPDATE ON Order_contains_items
FOR EACH ROW
SET NEW.Ordered_price =
(
SELECT Unit_price * NEW.Quantity_ordered
FROM Item
WHERE Item_id = NEW.Item_id
LIMIT 1
);
Here is SQLFiddle demo

Related

mysql auto increment from 00001 - 99999 and reset the value every year

My first aim is to generate customer reference code automaticaly everytime when I insert a new customer
so when it shown in my nodejs it should be : "MS2200001"
So my idea is set id from customer table (mysql) with auto increment and zerofill (int)
length = 5
So I can get id 00001
and insert to another column named as "customer reference"
with
("MS" + (2022)+ "00001")
And I am trying to reset the counter to 00001 again if become 2023,2024,2025 etc.
How can I archive this in phpmyadmin or I should chnage my idea?
Use trigger-generating technique and additional MyISAM table with secondary AUTO_INCREMENT column in PRIMARY KEY.
An example:
-- base table for complete identifier generation
CREATE TABLE base_for_complete_id (
`year` YEAR,
id INT AUTO_INCREMENT,
PRIMARY KEY (`year`, id)
) ENGINE = MyISAM;
-- create trigger which will generate complete identifier
CREATE TRIGGER generate_complete_id
BEFORE INSERT ON maintable
FOR EACH ROW
BEGIN
DECLARE tmp INT;
-- insert row into base table
INSERT INTO base_for_complete_id (`year`) VALUES (YEAR(NEW.created_at));
-- store id generated for current year
SET tmp = LAST_INSERT_ID();
-- save generated complete identifier into main table
SET NEW.complete_id = CONCAT('prefix_', YEAR(NEW.created_at), '_', tmp);
-- clear excess rows from base table
DELETE FROM base_for_complete_id WHERE `year` = YEAR(NEW.created_at) AND id < tmp;
END
DEMO fiddle
If you need to format id part of generated value with leading zeros then use LPAD() function, for example SET tmp = LPAD(LAST_INSERT_ID(), 5, 0);.
Caution! If the value for generated number exceeds 99999 then it will be truncated, and only 5 leading digits will be stored.

MySQL: Get average for values that correspond to a certain a ID

I am trying to create a table that contains the average review for every car model in a separate table. The output should look something like:
car_model_id
avg_stars
1
3
2
5
3
1
...
...
My approach to get this table is to use a function that calculates the average for every car_id that it is given. I started with the following but it yields an error because this format returns a table not an int. Also, the getAverage() function is not implemented correctly in the create table statement.
DELIMITER $$
CREATE FUNCTION getAverage(car_id_input int) RETURNS INT
BEGIN
SELECT AVG ( `car_id` ) /* To Fix */
FROM `car_user_reviews`
WHERE car_id = car_id_input;
END$$
CREATE TABLE `car_overall_stars` (
`car_id` INT NOT NULL,
PRIMARY KEY (`car_id`),
getAverage(car_id) AS `average_stars` FROM `car_user_reviews`, /* To Fix */
FOREIGN KEY (`actor_id`) REFERENCES `actor` (`actor_id`) ON DELETE RESTRICT ON UPDATE CASCADE
);
Any clues on how I can make this work? or any other approaches to take?
Using latest version of MySQL server.
As stated by #zedfoxus in the comment
create view car_rating_avg as select car_id, avg(review) from car_user_reviews group by car_id.

MySQL - How to insert or update from source table to target table with different Keys?

I have 2 tables with different structures.
CREATE TABLE test1
(
id INTEGER PRIMARY KEY,
EmpName VARCHAR(50),
Empid INTEGER
);
CREATE TABLE test2
(
Empid INTEGER PRIMARY KEY,
EmpFName VARCHAR(50),
EmpLName VARCHAR(50)
);
Is there a way to insert rows from test2 table into test1? If the row exists in test1 it should update the row as well. I think it's possible with Merge statement but it's not available for MySQL. Is there a similar function like this in MySQL?
I've looked into INSERT ... ON DUPLICATE KEY UPDATE but the tables should have the same primary keys.
I think this can help you.
Create Trigger to detect when insert/update data in your table test2.
Inside Trigger use REPLACE INTO to change data in your table test1.
Please check this link for additional of REPLACE INTO command.
Is there a way to insert rows from test2 table into test1? If the row exists in test1 it should update the row as well
UPDATE test1
JOIN test2 USING (Empid)
SET test1.EmpName = CONCAT_WS(' ', EmpFName, EmpLName)
Pay attention - EmpName max length is 50 whereas total length of combined name may be up to 50+1+50=101, so the combined value may be truncated. Increase max length for EmpName.
If you need to perform this operation automatically when the data in test2 is inserted/updated then use AFTER INSERT and AFTER UPDATE triggers, like
CREATE TRIGGER tr
AFTER INSERT -- and the same trigger on AFTER UPDATE event
ON test2
FOR EACH ROW
UPDATE test1
SET EmpName = CONCAT_WS(' ', NEW.EmpFName, NEW.EmpLName)
WHERE test1.Empid = NEW.Empid;

insert a new record into a mysql table with one of the values incremented by 1

I've got the following table:
productId price
1 price_value1
2 price_value2
3 price_value3
I would like to insert a new product into the table and assign it a new productId. In this case its value equals to 4.
So I want my new table to look like so:
productId price
1 price_value1
2 price_value2
3 price_value3
4 price_value4
So as far as I understand, in order to do that I have to somehow retrieve the max value of productId and insert it using INSERT INTO mytable VALUES (productId + 1, price_value4).
But how do I find out the maximum value of productId?
I tried INSERT INTO mytable VALUES (SELECT MAX(productId) + 1 FROM mytable, price_value4) but it didn't work.
This should Work:
Select the max(productID) and price_value4 as a columns from mytable and insert the result.
INSERT INTO mytable (SELECT MAX(productId) + 1, 'price_value4' FROM mytable);
However, if you are not going to jump some number you can just add an auto increment id key to product_id and then you will have only to insert the price, the product ID will be incremented automatically..
This will do so :
ALTER TABLE mytable
MODIFY COLUMN `productId` INT(10) UNSIGNED PRIMARY KEY AUTO_INCREMENT;
you can change INT(10) with the INT(5) for example depanding on the size you want to give to your productId column
EDIT :
In return to the OP question in comments why his solution wouldn't work
Some suggetions says you have to make the SELECT statment in insert always between parenthesis
INSERT INTO mytable VALUES ( (SELECT MAX(ID)+1 FROM mytable) , price_value4)
.. In my Case it Return
(1093): You can't specify target table
'mytable' for update in FROM clause
AND HERE IS WHY (Quoting From the documentation)
When selecting from and inserting into the same table, MySQL creates
an internal temporary table to hold the rows from the SELECT and then
inserts those rows into the target table. However, you cannot use
INSERT INTO t ... SELECT ... FROM t when t is a TEMPORARY table,
because TEMPORARY tables cannot be referred to twice in the same
statement
BUT there is away to overcome by using a query instead of the table itself in the FROM, which has the effect of copying the requested table values instead of referencing the one that you are updating..
INSERT INTO mytable VALUES (
(SELECT MAX(ID)+1 FROM (SELECT * FROM mytable ) as mytmp ),
'price_value4');
OR (Quoting From the documentation)
To avoid ambiguous column reference problems when the SELECT and the
INSERT refer to the same table, provide a unique alias for each table
used in the SELECT part, and qualify column names in that part with
the appropriate alias.
INSERT INTO mytable Values ( (SELECT MAX(ID)+1 FROM mytable as mytmp) , 'price_value4')
This is a duplicate question. In order to take advantage of the auto-incrementing capability of the column, do not supply a value for that column when inserting rows.
A simple syntax to create table
CREATE TABLE Product (
productId MEDIUMINT NOT NULL AUTO_INCREMENT,
price INT NOT NULL,
PRIMARY KEY (productid)
);
While inserting supplied default or leave column as blank or supplied value as NULL. Take a look at below code snippet.
INSERT INTO Product (price) VALUES
('10'),('20'),('4'),
('30');
refer this link

Using WHERE clause in ON DUPLICATE KEY UPDATE column

Here's the table design for a cartitems table
cartitems
cartitem_id PK AI
customer_id FK
item_id FK UNIQUE
item_quantity INT DEFAULT 1
What I need to accomplish
1.) if item_id exists in the table, increment the item_quantity by 1 everytime user clicks on "Add To Cart" button for the same item_id
2.) if item_id doesn't yet exist in the table, run an insert statement.
So what I did is this.
CREATE DEFINER=`root`#`localhost` PROCEDURE `addItemToCart`(aCustomerId int, aProductId int)
BEGIN
INSERT INTO cart_items(customer_id,product_id)
VALUES(aCustomerId,aProductId)
ON DUPLICATE KEY UPDATE
item_quantity = item_quantity + 1
WHERE customer_id = aCustomerId AND item_id = aProductId;
END
But when I inspected it, I get an error that says, missing semicolon at item_quantity = item_quantity + 1
I can't figure out what's causing the error. I don't know if it's a problem with the WHERE clause.
I'd appreciate any help.
Thanks.
The behavior of ON DUPLICATE KEY UPDATE is well explained in the documentation:
If you specify ON DUPLICATE KEY UPDATE, and a row is inserted that would cause a duplicate value in a UNIQUE index or PRIMARY KEY, MySQL performs an UPDATE of the old row
Looking at your table, you want to increment the quantity of an item for a given customer's cart. I am assuming here that a customer may only have one shopping cart at a time. So the conditions under which you want MySQL to perform an UPDATE rather than an INSERT is when the customer and item already appear in the table.
Towards this end, you can create a unique index on these two columns via:
CREATE UNIQUE INDEX unq_item_index ON cart_items (customer_id, item_id);
Then, you can use the following INSERT query:
INSERT INTO cart_items (customer_id, item_id)
VALUES
(aCustomerId, anItemId)
ON DUPLICATE KEY UPDATE
item_quantity = item_quantity + 1
WHERE customer_id = aCustomerId AND
item_id = anItemId;
Now the behavior will be that if a new entry for customer/item comes in, the item_quantity will be set to the default value of 1, otherwise the item_quantity will be incremented by 1.
BEGIN
IF NOT EXISTS(SELECT 1 FROM cart_items WHERE item_id = aProductId)
BEGIN
INSERT INTO cart_items(customer_id,product_id)
VALUES(aCustomerId,aProductId)
END
ELSE
UPDATE cart_items SET item_quantity = item_quantity + 1 WHERE customer_id = aCustomerId AND item_id = aProductId;
END
Why are you trying to use that WHERE clause there? It doesn't make sense. If DUPLICATE KEY happens it will UPDATE whatever field you specified to the old record that has the same key. So, if you just remove WHERE clause it should work. Check this article. It states the following two:
INSERT INTO table (a,b,c) VALUES (1,2,3)
ON DUPLICATE KEY UPDATE c=c+1;
UPDATE table SET c=c+1 WHERE a=1;
are the same.