mysql trigger one to many relation - mysql

So i have 3 tables Production, Stop_Prodcution and triggered_table.
production has a one to many realation with Stop_prodcution where a production can have a lot of stop prodcutions.
production table
-----------------------
id_prod | date
-----------------------
1 |20/03/2019
2 |18/04/2019
Stop_Production table
----------------------------
id_stop | name | id_prod
----------------------------
1 | Any reason | 1
2 | Lunch | 1
3 |damaged prod| 2
triggered_table
----------------------------
id|id_prod|date|id_stop|name
i've created 2 triggers:
after insert into production
for each row
insert into triggered_table
(id_prod,date) values (new.id_prod, curdate())
and the other one:
after update
set id_stop=new.id_stop,
name= new.name
where id_prod= new.id_prod
the problem is that a production record is able to have 2 or more stop_Production records so with the triggers that I have, it will update always the same record, but what I need is a new record with same information of production table and the information that differs from the new inserted row in stop_production, please tell me if I explained my self if not I'll try to be more clear.

This query will give you the results you want, without using a trigger:
SELECT
t1.id_stop,
t1.id_prod,
t1.`name`,
t2.date
FROM stop_production
LEFT JOIN production
ON (t1.id_prod = t2.id);
If you want to make a "table" out of this, you can create a view.
CREATE VIEW triggered_table AS (
SELECT
t1.id_stop,
t1.id_prod,
t1.`name`,
t2.date
FROM stop_production
LEFT JOIN production
ON (t1.id_prod = t2.id)
)
Then, if you want to SELECTfrom this "table", you can simply:
SELECT * FROM triggered_table;

Related

Sql Query to retrive data from table

How to retrieve odd rows from the table?
In the Base table always Cr_id is duplicated 2 times.
Base table
I want a SELECT statement that retrieves only those c_id =1 where Cr_id is always first as shown in the output table.
Output table
Just see the base table and output table you should automatically know what I want, Thanx.
Just testing min date should be enough
drop table if exists t;
create table t(c_id int,cr_id int,dt date);
insert into t values
(1,56,'2020-12-17'),(56,56,'2020-12-17'),
(1,8,'2020-12-17'),(56,8,'2020-12-17'),
(123,78,'2020-12-17'),(1,78,'2020-12-18');
select c_id,cr_id,dt
from t
where c_id = 1 and
dt = (select min(dt) from t t1 where t1.cr_id = t.cr_id);
+------+-------+------------+
| c_id | cr_id | dt |
+------+-------+------------+
| 1 | 56 | 2020-12-17 |
| 1 | 8 | 2020-12-17 |
+------+-------+------------+
2 rows in set (0.002 sec)
What you're looking for could be "partition by", at least if you're working on mssql.
(In the future, please include more background, SQL is not just SQL)
https://codingsight.com/grouping-data-using-the-over-and-partition-by-functions/
I have an old query lying around, that is able to put a sorting index on data who lacks this, although the underlying reason is 99.9% sure to be a bad data design.
Typically I use this query to remove bad data, but you may rewrite it to become a join instead, so that you can identify the data you need.
The reason why I'm not putting that answer here, is to point out, bad data design results in more work when reading it afterwards, whom seems to be the real root cause here.
DELETE t
FROM
(
SELECT ROW_NUMBER () OVER (PARTITION BY column_1 ,column_2, column_3 ORDER BY column_1,column_2 ,column_3 ) AS Seq
FROM Table
)t
WHERE Seq > 1

How to copy a table (MySQL) and automatically update the new one?

I want to create a small copy of a bigger table and link both of them.
Every time I make an update in the bigger one, I want that the small one updates too.
For example, I have this data:
Big table:
id | name | price
1 | a | 10
2 | b | 12
Small table:
id | name
1 | a
2 | b
---- UPDATING THE BIGGER ONE ---
Big table:
id | name | price
1 | y | 10
2 | b | 12
3 | c | 13
Small table should become AUTOMATICALLY (after I update the bigger one):
id | name
1 | y
2 | b
3 | c
Do you know how to do it?
To do exactly what you're asking you could use triggers. Triggers are SQL that execute automatically when certain events happen. To mirror the data you would need to create UPDATE, INSERT, and DELETE triggers. (I don't have access to a MySQL instance at the moment to test, so there could be typos)
CREATE TRIGGER big_to_small_insert
AFTER INSERT ON big
FOR EACH ROW
INSERT INTO small (id, name) VALUES (NEW.id, NEW.name)
CREATE TRIGGER big_to_small_update
AFTER UPDATE ON big
FOR EACH ROW
UPDATE small SET name = NEW.name WHERE id = NEW.id
CREATE TRIGGER big_to_small_delete
AFTER DELETE ON big
FOR EACH ROW
DELETE FROM small WHERE id = OLD.id
However, a View is probably a better option if the "small" table is truly just the big table with a subset of data. A View won't store a copy of the data, so if you update the table (big) it will be reflected in the view (small), but the opposite is also true. If you do an INSERT, UPDATE, or DELETE on the view (small) it will actually happen in the table (big).
CREATE VIEW small AS
SELECT id, name FROM big

mysql trigger with inner join

I have 3 tables in mysql database that is linked to my issue tracker.
tables are:
1.Issues (contains ID, Issue_name & assignee)
2.change_group (contains ID, Issue_id, created_time)
3.change_item (contains id, group_id,field, old string , new string)
when any change occures about my isuues like changing status or assignee of issue,
table change_group will have new record. one goupid is matched with one or more records in change_item table. for example on group_id can save change in status and assignee of an issue:
now
according to changing assignees of issue I added a column with assignee name into issue table and I want to have a trigger that save snapshot of assigee field when a change happens.and I tried this:
create TRIGGER save_Assignee AFTER INSERT ON changeitem
FOR EACH ROW
BEGIN
SET new.assignee=(select assignee from jiraissue INNER JOIN changegroup ON jiraissue.ID=changegroup.issueid)
END
It seems that I cant Have inner join with trigger at same time.
If anyone has any thoughts on this it would be much appreciated. Thanks
MINA
table "issues"
id | Issue_name | Assignee
11 | R&D | User1
table "changegroup"
id | issue_ID | Created_time
12 | 11 | 2015/2/2 16:40
table "change_item"
id | group_id | field | old string | new string
13 | 12 |status | to do | in progress
I want to have a trigger to save who is assignee at the time that change happens on an issue?
You want a before insert trigger, not an after insert trigger:
create TRIGGER save_Assignee BEFORE INSERT ON changeitem
FOR EACH ROW
BEGIN
SET new.assignee=(select assignee from jiraissue INNER JOIN changegroup ON jiraissue.ID = changegroup.issueid)
END
I also suspect that your subquery is all wrong. It probably returns too many rows, because it needs a reference to new. However, that is not your question. If you decide that you have such problems, then ask another question, with sample data and desired results.

SQL checking duplicates in one column and deleting another

I need to delete around 300,000 duplicates in my database. I want to check the Card_id column for duplicates, then check for duplicate timestamps. Then delete one copy and keep one. Example:
| Card_id | Time |
| 1234 | 5:30 |
| 1234 | 5:45 |
| 1234 | 5:30 |
| 1234 | 5:45 |
So remaining data would be:
| Card_id | Time |
| 1234 | 5:30 |
| 1234 | 5:45 |
I have tried several different delete statements, and merging into a new table but with no luck.
UPDATE: Got it working!
Alright after many failures I got this to work for DB2.
delete from(
select card_id, time, row_number() over (partition by card_id, time) rn
from card_table) as A
where rn > 1
rn increments when there are duplicates for card_id and time. The duplicated, or second rn, will be deleted.
I strongly suggest you take this approach:
create temporary table tokeep as
select distinct card_id, time
from t;
truncate table t;
insert into t(card_id, time)
select *
from tokeep;
That is, store the data you want. Truncate the table, and then regenerate it. By truncating the table, you get to keep triggers and permissions and other things linked to the table.
This approach should also be faster than deleting many, many duplicates.
If you are going to do that, you ought to insert a proper id as well:
create temporary table tokeep as
select distinct card_id, time
from t;
truncate table t;
alter table t add column id int auto_increment;
insert into t(card_id, time)
select *
from tokeep;
If you haven't Primary key or Candidate key probably there is no option using only one command. Try solution below.
Create table with duplicates
select Card_id,Time
into COPY_YourTable
from YourTable
group by Card_id,Time
having count(1)>1
Remove duplicates using COPY_YourTable
delete from YourTable
where exists
(
select 1
from COPY_YourTable c
where c.Card_id = YourTable.Card_id
and c.Time = YourTable.Time
)
Copy data without duplicates
insert into YourTable
select Card_id,Time
from COPY_YourTabl

Mysql Update / Insert: copying historical data

I have some historical data tables in my Mysql database.
I want to repeat a day's historical data for another day in the same table.
Table structure, with some sample data:
Id | Date | Value
1 | 2012-04-30 | 5
2 | 2012-04-30 | 10
3 | 2012-04-30 | 15
I want to repeat those ids & values, but for a new date - e.g. 2012-05-01. i.e. adding:
1 | 2012-05-01 | 5
2 | 2012-05-01 | 10
3 | 2012-05-01 | 15
I feel that there should be a straightforward way of doing this... I've tried playing with UPDATE statements with sub-queries and using multiple LEFT JOINs, but haven't get there yet.
Any ideas on how I can do this?
EDIT: To clarify...
- I do NOT want to add these to a new table
- Nor do I want to change the existing records in the table.
- The ids are intentionally duplicated (they are a foreign_key to another table that records what the data refers to...).
INSERT INTO yourTable
SELECT ID, "2012-05-01" As Date, Value
FROM yourTable
WHERE Date = "2012-04-31"
Usually, your ID would be an autoincrement though, so having the same ID in the same table would not work. Either use a different ID, or a different table.
Different ID (next autoincrement):
INSERT INTO yourTable
SELECT NULL as ID, "2012-05-01" As Date, Value
FROM yourTable
WHERE Date = "2012-04-31"
Different table (referring to original ID)
INSERT INTO yourTable_hist
SELECT NULL as ID, ID as old_ID, "2012-05-01" As Date, Value
FROM yourTable
WHERE Date = "2012-04-31"
Maybe something like this:
UPDATE Table1
SET Date=DATE_ADD(Date, INTERVAL 1 DAY)
Or if you want to insert them to a new table:
INSERT INTO Table1
SELECT
ID,
DATE_ADD(Date, INTERVAL 1 DAY),
Value
FROM
Table2