Change FK placement - mysql

I have table1
id | some_field
----------------
1 | text1
2 | text2
3 | text3
And table2
id | table1_id | some_field
----------------------------
1 | 3 | lorem ipsum
2 | 1 | lorem ipsum
3 | 2 | lorem ipsum
There are one to one relations between table1.id and table2.table1_id fields.
I need to change FK placement to table1 (means create table2_id in table1 and fill it with related keys form table2) to get structure like this:
id | table2_id | some_field
---------------------------
1 | 2 | text1
2 | 3 | text2
3 | 1 | text3
And then drop table1_id field (but it's not related to the question).
The question is can I make it with like one common SQL statement that will update all rows with saving of current relationships?

An UPDATE statement can update rows from one or more JOIN-ed tables.
Assuming you have already created the column table2_id in table1, your UPDATE query should be like this:
UPDATE table1
INNER JOIN table2 ON table1.id = table2.table1_id
SET table1.table2_id = table2.id
That's all. It should report as modified the same number of rows there are in table1 (or in table2, they should have the same number of rows).

This is done with a simple join.
alter table t1 add column table2_id int;
update t1 join t2 on t1.id = t2.table1_id
set t1.table2_id = t2.id;
see it working live in an sqlfiddle

If I got it right
UPDATE table2
JOIN table1 ON (table2.table1_id = table1.ID)
SET table2.ID = table2.table1_id
, table2.table2_id = table2.ID
, table2.some_field = table1.some_field;

Related

MySQL: Update table column with id from other table by string compare

I have two tables with a VARCHAR column called "name1" and "name2":
table1:
id | name1
1 | xyz
2 | foo
3 | barfoo
4 | xchad
table2:
id | id_table1 | name2
1 | NULL | xchad
2 | NULL | foo
3 | NULL | hade
4 | NULL | bar
I want to update the column id_table1 of table2 with the respective id from table1 where the rows name1 and name2 match.
For example in table2 the first row should be updated with 4 in column id_table1 since 'xchad' = 'xchad'.
A join simply takes too much time with the string compare.
Thank you!
Consider:
UPDATE table1 t1
INNER JOIN table2 t2 ON t2.name2 = t1.name1
SET t2.id_table1 = t1.id
With indexes on table1(name1) and table2(name2), this should perform efficiently.
An alternative is to use a correlated subquery:
UPDATE table2 t2
SET t2.id_table1 = (
SELECT t1.name1 FROM table1 t1 WHERE t1.name1 = t2.id_table1
)
Please note that this second solution does require each name in table2 to have a unique match in table1.

MySQL select multiple row on table 2 with two differents Id from table 1 result in one row as two differents fields

Is it possible in only one MySQL query to get the desired result (below) returned into one row ?
Where id=1 in Table 1
Table 1
|------|----------|----------|
| id | refIdOne | refIdTwo |
|------|----------|-----------
| 1 | 1 | 2 |
|------|----------|-----------
Columns "refIdOne" & "refIdTwo" refer Table 2 "id" column
Table 2
|------|------------------|
| id | text |
|------|------------------|
| 1 | cheese |
| 2 | made with milk |
|------|------------------|
Desired result returned in ONE ROW with custom AS columns named "subject" and "description" :
|----------|-----------------|
| subject | description |
|----------|-----------------|
| cheese | made with milk |
? Many thanks for help
* EDIT : Answer is *
select t21.text as subject, t22.text as description
from Table1 as t1
join Table2 as t21 on t1.refidone = t21.id
join Table2 as t22 on t1.refidtwo = t22.id
where t1.id = 1
Table2 has to joined twice to Table1.
select t21.text as subject, t22.text as description
from table1 t1
join table2 t21 on t1.refidone = t21.id
join table2 t22 on t1.refidtwo = t22.id
You need to perform Self join. Join Table2.ID twice with Table1.refIdOne and Table1.refIdTwo
select t2.text as subject, t3.text as description
from Table1 t1
Left join Table2 t2 on t1.refIdOne = t2.id
Left join Table2 t3 on t1.refIdTwo = t2.id
without joins
SELECT
(SELECT text FROM Table2 WHERE id = (SELECT refIdOne FROM Table1 WHERE id = 1) ) AS name,
(SELECT text FROM Table2 WHERE id = (SELECT refIdTwo FROM Table1 WHERE id = 1) ) AS description

update rows after left join

I'm looking for a way to update some values in a table if they were used in a left join.
I have two tables:
table1:
id | name | age | job
1 | john | 31 |
2 | eric | 25 |
table2:
id | job | inserted
1 | lawyer | 0
2 | dentist | 1
3 | cop | 0
Then I run the query:
UPDATE table1
LEFT JOIN
table2
ON table1.id = table2.id
SET table1.job = `table2.job`
WHERE table2.inserted = 0
But I want to update the rows from table2 that were used in the update so they have inserted = 1. This for two reasons 1) to speed up the join and 2) so I can check which rows of table2 were not used. (The inserts in table2 happen before table1, but the ids in table2 should always be present in table1 if all cron jobs run okay.)
You shouldn't be using a LEFT JOIN, since you only want to update rows in table1 that have a matching row in table2. Try:
UPDATE table1 AS t1
JOIN table2 AS t2 ON t1.id = t2.id
SET t1.job = t2.job, t2.inserted = 1
WHERE t2.inserted = 0
DEMO

Update table new column with values from another table (MySQL)

I have two tables table1 and table2.
I'm doing some changes and I realized that table2 is not needed, but this table has lots of data already and I need to pass the values of ID_B from table2 to table1.
Here's the structure:
table1
ID_table1 | ID_table2 | ID_B
1 | 1 |
2 | 3 |
3 | 1 |
4 | 2 |
table2
ID_table2 | ID_B
1 | 14
2 | 26
3 | 26
So what I want is the MySQL query to pass the ID_B value from table2 to table1 when the ID_table2 on table1 is equal to the ID_table2 on table2.
For example, the row on table1 where the ID_table1 is 1 would have the ID_B = 14.
Can you help me on this?
Thanks in advance,
Miguel.
Using JOINs you can do as.
update table1 t1
inner join
table2 t2 on t2.ID_table2 = t1.ID_table2
set t1.ID_B = t2.ID_B
DEMO
You could try it like so:
UPDATE
table1 AS target,
(SELECT ID_table2, ID_B FROM table2) AS source
SET
target.ID_B = source.ID_B
WHERE
target.ID_TABLE2 = source.ID_table2

Multiple data check in one query

I have the following problem. I have 2 tables in the database - table1 and table2.
Table1
id| val1| val2
--------------
1 | 234 | 342
2 | 325 | 356
...
Table2
id | uid | val
--------------
1 | 5 | 234
2 | 6 | 362
3 | 5 | 123
I would like to check for each record in table2 if val exists in table1 (table2.val=table1.va1 or table2.val > table1.vall).
In table1 is about 2 million records. In table2 several thousand.
If query result true i'd like to remove rows from table2.
Is it possible to do this in one query? mysql or postgresql
Performance is very important.
Assuming (t2.val = t1.val1) or (t1.val2 > t2.val) conditions:
delete table2
from table2 t2
inner join table1 t1 on (t2.val = t1.val1) or (t1.val2 > t2.val)
delete t
from #table2 t
inner join #table1 t2
on t.val = t2.val or t2.val>t.val
Assuming uid in Table2 reference id in Table1 (and that neither table contain nulls), this returns the rows in Table1 that satisfy your existence criteria:
SELECT *
FROM Table1
WHERE EXISTS (
SELECT *
FROM Table2
WHERE Table2.uid = Table1.id
AND (
Table2.val = Table1.val1
OR Table2.val > Table1.val2
)
);