Reputation:
Let's assume I have the table:
id | val_1 | val_2
1 | 1 | 0
2 | 1 | 1
3 | 1 | 2
4 | 2 | 0
val_2 should be zero at first if there was no rows with val_1 before. Otherwise it should be previous val_2 + 1 for this val_1.
I can't figure it out by myself the best way to do it. The one thing I've invented is trigger after insert, but I think here maybe some other way to do it cleaner and faster? My code is something like:
DELIMITER $$
CREATE TRIGGER after_table_insert
AFTER INSERT
ON table FOR EACH ROW
BEGIN
UPDATE table SET val_2 = t.val_2 + 1
FROM (
SELECT val_2 FROM table WHERE val_1 = new.val_1 ORDER BY id DESC LIMIT 1
) t
WHERE id = new.id;
END$$
DELIMITER ;
I will appreciate for any help! Have a great day/night.
Upvotes: 2
Views: 38
Reputation: 970
You have couple of issues with such setup:
What's going on if you UPDATE or DELETE rows? It can mess up everything with val2. Be careful with that.
Val2 can always be calculated and there is no need to store it.
Having said that, below I will show you a setup with which I will store only id and val1. Then val2 will be calculated within the SELECT statement (so it will always be correct).
CREATE TABLE vals(
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
val INT NOT NULL
);
INSERT INTO vals(val) VALUES(1),(1),(1),(2);
Now what I am going to do is to use the ROW_NUMBER() function (which prints the row number) and run it over a PARTITION BY val:
SELECT id, val,
ROW_NUMBER() OVER (
PARTITION BY val
) AS val2
FROM vals;
We are almost there. Sadly it will offset them by 1 compared to what you need:
+----+-----+------+
| id | val | val2 |
+----+-----+------+
| 1 | 1 | 1 |
| 2 | 1 | 2 |
| 3 | 1 | 3 |
| 4 | 2 | 1 |
+----+-----+------+
The fix is simple. Just add "-1" to it and you are ready.
SELECT id, val,
-1+ROW_NUMBER() OVER (
PARTITION BY val
) AS val2
FROM vals;
This will produce:
+----+-----+------+
| id | val | val2 |
+----+-----+------+
| 1 | 1 | 0 |
| 2 | 1 | 1 |
| 3 | 1 | 2 |
| 4 | 2 | 0 |
+----+-----+------+
With this solution there is no need to store val2 at all (you can create it as a VIEW if you wish) and it is not vulnerable to the issue when you delete a row (it will continue to work properly).
Upvotes: 1
Reputation: 49373
This is one possibility
Schema (MySQL v5.7)
CREATE TABLE table1 (
`id` INTEGER,
`val_1` INTEGER,
`val_2` INTEGER
);
DELIMITER //
CREATE TRIGGER after_table_insert
BEFORE INSERT
ON table1 FOR EACH ROW
BEGIN
SET @maxval2 = 0;
SELECT max(val_2) + 1 into @maxval2 FROM table1 WHERE val_1 = new.val_1;
IF @maxval2 IS NULL THEN
SET @maxval2 = 0;
END IF;
SET NEW.val_2 = @maxval2;
END//
DELIMITER ;
INSERT INTO table1
(`id`, `val_1`, `val_2`)
VALUES
('1', '1', '0'),
('2', '1', '0'),
('3', '1', '0'),
('4', '2', '0'),
('4', '2', '0');
Query #1
SELECT * FROM table1;
| id | val_1 | val_2 |
| --- | ----- | ----- |
| 1 | 1 | 0 |
| 2 | 1 | 1 |
| 3 | 1 | 2 |
| 4 | 2 | 0 |
| 4 | 2 | 1 |
Upvotes: 0