how to update a table after fetching the data from other table - mysql

I have two table as follows:
active_employee, with the columns id, email_id, job, location and project_id
project_relation, with the columns id, email_id and project_id.
My problem is that I want to update the project_id column of project_relation table with the condition that if the value for project_id in both the tables are not same, then it has to fetch the value from "active_employee" table and update the project_relation table for corresponding email_id.
Help me how to do this!

I believe an UPDATE FROM with a JOIN will help:
UPDATE
project_relation
SET
project_relation.project_id = active_employee.project_id
FROM
project_relation PR
INNER JOIN
active_employee AE
ON
PR.columns_id = AE.columns_id
Just check underscore.. it may create problem.. you can remove it and make changes in db columns names also.
or Simply try this-
UPDATE project_relation SET project_relation.project_id = active_employee.project_id where project_relation.columns_id = active_employee.columns_id;

I think I get what you need. I created some temp tables to replace your actual tables for testing.
I used a subquery to rename some of the column names to remove ambiguous names because of the update table:
DECLARE #ACTIVE_EMPLOYEE TABLE (columnid UNIQUEIDENTIFIER, emailid UNIQUEIDENTIFIER, job VARCHAR(200), location VARCHAR(200), projectid UNIQUEIDENTIFIER)
DECLARE #PROJECT_RELATION TABLE (columnid UNIQUEIDENTIFIER, emailid UNIQUEIDENTIFIER, projectid UNIQUEIDENTIFIER)
UPDATE #PROJECT_RELATION
SET projectid = active.proid
FROM (SELECT columnid,
emailid [emid],
job,
location,
projectid [proid]
FROM #ACTIVE_EMPLOYEE) active
WHERE active.emid = emailid
AND active.proid <> projectid

Related

Insert Foreign key into Table according to its Primary Key

I am trying to to split a table into two table and want to add the reference (foreign key) of one table to another
For Example lets say there are is a table called customer table and an Column in it called Group Name has repetitive data which goes against data normalization, so I want to split the table on that column, which would be to replace that Group name Column with GroupID column
NOW form a new table with 2 column GroupID and Group Name and insert distinct Group values into GroupName column, with an auto-incrementing GroupID which will be the Primary key in the group table, and be refrenced in Customer table to act as a foreign key
Now the main question is how to Insert those Autoincremented GroupID of 'GROUP TABLE' into groupID of the customer Table or how do You Insert Foreign Keys into Customer Table According to the Main table
The customerTable With GroupID and customerTable With Customer_Group are two diffrent table
UPDATE ch03.customerd
JOIN ch03.group gr ON customer.Customer_Group = gr.Group_Name
SET customerd.Group_ID = gr.Group_id
WHERE customerd.Customer_id = customer.Customer_id;
update ch03.customerd set Group_ID =
(select gr.Group_id
from ch03.customer as co
join ch03.group as gr on co.Customer_Group = gr.Group_Name)
where customerd.Customer_id = customer.Customer_id;
this is what i have tried and isn't working
If all data except group_id is already transferred then
UPDATE new_customer_table nc
JOIN old_customer_table oc ON nc.customer_id = oc.customer_id
JOIN new_group_table ng ON oc.customer_group = ng.group_name
SET nc.group_id = ng.group_id
If new tables are empty yet then
INSERT INTO new_group_table (group_name)
SELECT DISTINCT customer_group
FROM old_customer_table;
INSERT INTO new_customer_table (customer_id, .. , customer_age, group_id)
SELECT oc.customer_id, .. , oc.customer_age, ng.group_id
FROM old_customer_table oc
JOIN new_group_table ng ON oc.customer_group = ng.group_name;
PS. If customer_group in old table is not defined as ENUM / have no CHECK constraint which checks entered values for validity then I recommend to execute INSERT INTO new_group_table .. firstly and check the values inserted carefully. If some misprintings will be found then you need to edit source data before, then truncate new_group_table and repeat - until all group names are correct.

Appending data from another database

I'm trying to add an age column to a database (junecustomers) using a DOB column from an existing database (customerdata).
I have a matching firstname, lastname, and customerid column in both data sets. In the customerdata data set, I have the DOB column that I want to use to calculate the age. Is this correct?
select * from junecustomers
left join customerdata
on junecustomers.customerid = customerdata.customerid
alter table (junecustomers)
add select
trunc(months_between(sysdate, dob)/12) Age from customerdata
Note: the customerdata database has multiple entries for some of the customers but the junecustomers database has only one entry per customer.
You need to run two scripts, one to add the column and one to update the data, e.g.:
ALTER TABLE junecustomers
ADD COLUMN age INT;
UPDATE junecustomers jc
SET jc.age = (SELECT trunc(months_between(sysdate, dob)/12) FROM customerdata
WHERE customerid = jc.customerid LIMIT 1);

MySQL loop for every row and update

I have table called users and for example it looks like:
Name ID
Tom 1
Al 55
Kate 22
...
The problem is: the IDs are not in sequence.
I would like to give them new IDs from 1 to length of users. I would like to declare some var=1 and make UPDATE in loop and give them new ID = var, and later do var=var+1 until var <= users length
How can I do this?
Thank you very much!
Here is how you would do that in MySQL. Just run this:
set #newid=0;
update users set ID = (#newid:=#newid+1) order by ID;
If the ID in the Users table is not referenced by other tables by FK, the following query can update the ID in the table to have new consecutive values:
CREATE TABLE IF NOT EXISTS tmpUsers (
ID int not null,
newID int not null auto_increment primary key
) engine = mysisam;
INSERT INTO tmpUsers (ID,newID)
SELECT ID,NULL
FROM users
ORDER BY ID;
UPDATE users u INNER JOIN tmpUsers t
ON u.ID=t.ID
SET u.ID=t.NewID;
DROP TABLE IF EXISTS tmpUsers;
Test script:
CREATE TABLE users (ID int not null, name nvarchar(128) not null);
INSERT users(ID,name)
VALUES (1,'aaa'),(4,'bbb'),(7,'ggg'),(17,'ddd');
SELECT * FROM users;

Should I use cursors in my SQL procedure?

I have a table that contains computer login and logoff events. Each row is a separate event with a timestamp, machine name, login or logoff event code and other details. I need to create a SQL procedure that goes through this table and locates corresponding login and logoff event and insert new rows into another table that contain the machine name, login time, logout time and duration time.
So, should I use a cursor to do this or is there a better way to go about this? The database is pretty huge so efficiency is certainly a concern. Any suggested pseudo code would be great as well.
[edit : pulled from comment]
Source table:
History (
mc_id
, hs_opcode
, hs_time
)
Existing data interpretation:
Login_Event = unique mc_id, hs_opcode = 1, and hs_time is the timestamp
Logout_Event = unique mc_id, hs_opcode = 2, and hs_time is the timestamp
First, your query will be simpler (and faster) if you can order the data in such a way that you don't need a complex subquery to pair up the rows. Since MySQL doesn't support CTE to do this on-the-fly, you'll need to create a temporary table:
CREATE TABLE history_ordered (
seq INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
hs_id INT,
mc_id VARCHAR(255),
mc_loggedinuser VARCHAR(255),
hs_time DATETIME,
hs_opcode INT
);
Then, pull and sort from your original table into the new table:
INSERT INTO history_ordered (
hs_id, mc_id, mc_loggedinuser,
hs_time, hs_opcode)
SELECT
hs_id, mc_id, mc_loggedinuser,
hs_time, hs_opcode
FROM history ORDER BY mc_id, hs_time;
You can now use this query to correlate the data:
SELECT li.mc_id,
li.mc_loggedinuser,
li.hs_time as login_time,
lo.hs_time as logout_time
FROM history_ordered AS li
JOIN history_ordered AS lo
ON lo.seq = li.seq + 1
AND li.hs_opcode = 1;
For future inserts, you can use a trigger like below to keep your duration table updated automatically:
DELIMITER $$
CREATE TRIGGER `match_login` AFTER INSERT ON `history`
FOR EACH ROW
BEGIN
IF NEW.hs_opcode = 2 THEN
DECLARE _user VARCHAR(255);
DECLARE _login DATETIME;
SELECT mc_loggedinuser, hs_time FROM history
WHERE hs_time = (
SELECT MAX(hs_time) FROM history
WHERE hs_opcode = 1
AND mc_id = NEW.mc_id
) INTO _user, _login;
INSERT INTO login_duration
SET machine = NEW.mc_id,
logout = NEW.hs_time,
user = _user,
login = _login;
END IF;
END$$
DELIMITER ;
CREATE TABLE dummy (fields you'll select data into, + additional fields as needed)
INSERT INTO dummy (columns from your source)
SELECT * FROM <all the tables where you need data for your target data set>
UPDATE dummy SET col1 = CASE WHEN this = this THEN that, etc
INSERT INTO targetTable
SELECT all columns FROM dummy
Without any code that you're working on.. it'll be hard to see if this approach will be any useful.. There may be some instances when you really need to loop through things.. and some instances when this approach can be used instead..
[EDIT: based on poster's comment]
Can you try executing this and see if you get the desired results?
INSERT INTO <your_target_table_here_with_the_three_columns_required>
SELECT li.mc_id, li.hs_time AS login_time, lo.hs_time AS logout_time
FROM
history AS li
INNER JOIN history AS lo
ON li.mc_id = lo.mc_id
AND li.hs_opcode = 1
AND lo.hs_opcode = 2
AND lo.hs_time = (
SELECT min(hs_time) AS hs_time
FROM history
WHERE hs_time > li.hs_time
AND mc_id = li.mc_id
)

Update Junction table in many-to-many relationship

This is a follow up question to this one:
Query examples in a many-to-many relationship
regarding updating the junction table. To do this, I would have to use both key values in the junction table, in the WHERE clause.
Users UserAddresses Addresses
======= ============= =========
FirstName UserId City
LastName AddressId State
Zip
In this example, for instance, say I wanted to update the AddressId field in the UserAddresses table, because a user changed his address. I would have to use both the existing UserId and the address AddressId in the update WHERE clause.
I'm using a stored procedure, and passing in UserId and the new AddressId as parameters.
I've tries this:
CREATE PROCEDURE dbo.test
(
#UserId int,
#AddressId int
)
AS
create table #temp
(
UserId int not null,
AddressId int not null
)
insert into #temp select UserId, AddressId from UserAddresses where UserId = #UserId
update UserAddresses
set AddressId = #AddressIdD
WHERE (UserId+AddressId in #temp table = UserId+AddressId passed in as parameters)??
I've tried all sorts of combinations, but I can't seem to get the syntax right.
The UserId passed in, would ofcourse be the same as the one in the UserAddresses table, but this is just me trying some things. The WHERE clause is where it seems to go wrong.
Any thoughts?
This actually looks like a many-to-one relationship. If it's not you'll need the old address id as well as the new address id and user id to make the change. If it's a many to one relationship then a simple update should work since only one user id/address id pair will exist for each user id:
update UserAddresses
set AddressId = #AddressId
where UserId = #UserId
If it truly is a many-to-many relationship you need to find the existing pair out of many possible ones and update that one -- that's where you'll need both the new and old address ids in addition to the user id.
update UserAddresses
set AddressId = #NewAddressId
where UserId = #UserId and #AddressId = #OldAddressId
Why use the temp table?
CREATE PROCEDURE dbo.test
(
#UserId int,
#AddressId int
)
AS
update UserAddresses
set AddressId = #AddressIdD
WHERE UserId = #UserId
tvanfossom pointed out the problem in your code correctly, I think.
With the tables above, your operation could be done in various ways:
INSERT the link to the new address and DELETE the link to the old address, either keeping or deleting the address record that's being linked to.
UPDATE the link record as tvanfossom described (LuckyLindys query will set all registered addresses of the user to the same one).
UPDATE the address record that's being linked to.
Which one you use depends on what you want in your application. I'd probably just update the linked address, or do you need to keep the old one?