Currently to get data updated in Table3 that depends on conditions in Tables1 and Table2 I am doing this:
Update Table_B as T1
Inner Join Table_A as T2
On T1.S_ID=T2.ID
Set T1.Percent = T2.Percent
Update Table_C as T1
Inner Join Table_B as T2
On T1.ID=T2.J_ID
Set T1.B = T2.B
Where T2.Percent=100
I would like to not store or update TableB with TableA Percent and somehow do the join in a single statement.
update table_b T1 set T1.Percent=(select T2.Percent from table_a T2 where T1.S_ID=T2.ID)
update table_c T1 set T1.B=(select T2.B from table_b T2 where T1.ID=T2.J_ID) where exists(select * from table_b T3 where T1.ID=T3.J_ID and T3.percent=100)
This isn't valid syntax in an UPDATE statement
Set T1.Percent as T1.Percent
^^
And this isn't valid
Set T1.B as T2.B
^^
The syntax in the UPDATE statements in the question do not look valid.
The SET assignment operator is an equals sign, not an As keyword.
And T1.Percent = T1.Percent doesn't make much sense, since there doesn't seem to be any point to setting a column to its current value.
It's not clear what it is you are actually trying to achieve, without some example data, and the desired end result.
To write a multi-table UPDATE statement, I first write a SELECT statement that returns the primary (or unique) keys of the tables that I am going to update, along with the current values of the columns to be updated, and expressions that return the new values that are going to be assigned to the columns
Based on the SQL in the question, it looks like you might want two joins, something like this:
SELECT ...
FROM table_a a
JOIN table_b b
ON b.s_id = a.id
JOIN table_c c
ON c.id = b.j_id
WHERE a.percent = 100
ORDER BY ...
(We don't know anything about the cardinality of the columns and relationships, whether those are one-to-one, one-to-many, zero-or-one-to-one, etc. We're just guessing.)
To evaluate and test the query, I'd include the primary keys of the tables. I'm going to guess id is the primary key of (the unfortunately named) Table_A and Table_C. And guess that the tuple (j_id,s_id) is a UNIQUE KEY in Table_B.
I will also include the column to be updated (to show the current value), and an expression that returns the new value to be assigned to the column.
Something like this:
SELECT a.id AS `a__id`
, a.percent AS `a__percent`
, b.j_id AS `b__j_id`
, b.s_id AS `b__s_id`
, c.id AS `c__id`
, c.b AS `c__b_old`
, b.b AS `c__b_new`
FROM table_a a
JOIN table_b b
ON b.s_id = a.id
JOIN table_c c
ON c.id = b.j_id
WHERE a.percent = 100
ORDER
BY c.id
, a.id
I would test that, and make sure it's returning the rows from Table_C that I want to update, and that the value returned for the c__b_new expression is the value that I want to assign to the b column in Table_C.
Once I get the SELECT statement working correctly (and only after I get it working correctly), I convert that to a multitable UPDATE.
Just replace the SELECT ... FROM part with the keyword UPDATE.
And before the WHERE clause, add a SET clause that does the assignment of the new value to the column. (I use the same expression I used in the SELECT list to return the new value.)
UPDATE table_a a
JOIN table_b b
ON b.s_id = a.id
JOIN table_c c
ON c.id = b.j_id
SET c.b = b.b
WHERE a.percent = 100
That's just an example of how I go about writing a multi-table UPDATE. There is no guarantee that this statement is going to work for what you need. Again, it's not clear what you are trying to achieve; the specification is too vague; so we're only guessing.
Related
I have two similar tables with the same columns and same type of data. The goal is to get the data of table_a but replace all entries with table_b values if there are value with the same id.
So I have the following two selects:
SELECT table_a.id, table_a.text
and
SELECT table_b.id, table_b.text
In pseudo code:
iterate table_a data
if table_a.id == table_b.id then
table_out.id = table_b.id
table_out.text = table_b.text
else
table_out.id = table_a.id
table_out.text = table_a.text
end if
end iterate
The tables table_a and table_b data shall not be touched. Just the output of the select shall contain the data.
I was thinking first of joining the two tables with a left join. Then I would need a kind of if to switch columns for the select.
Thank you.
I would recommend coalesce() for this purpose:
select a.id,
coalesce(b.text, a.text) as text
from table_a a left join
table_b b
on a.id = b.id
order by a.id;
You can use LEFT JOIN it will give you all table_a record and common record between two tables. then use case logic to get require output
SELECT
t1.id,
(CASE WHEN t1.id=t2.id THEN t2.text ELSE t1.text END) AS text
FROM table_a t1
LEFT JOIN table_b t2
ON t1.id=t2.id
ORDER BY t1.id
DEMO
I want to update a field, let's call it 'field_A', in table 'table_A' with the maximum value that exists of field 'field_B' in 'table_B', but only IF there is a max value for that field 'field_B' in table 'table_B'.
Table 'table_B' has a 'reference' field which contains the 'id' of the table_A record we want to update.
Now I have the following query, which works perfectly.
UPDATE table_A a SET a.field_A = (SELECT MAX(b.field_B)
FROM table_B WHERE b.reference = a.id)
WHERE a.id IN (
SELECT reference
FROM table_B
GROUP BY reference
HAVING COUNT(reference) > 0
)
So it only updates field_A IF there are records found for that reference because I don't want to end up setting fields 'field_A' to zero when no related records were found.
As I said before, this query already works perfectly, but now I have to run a query for table_B two times, which seems a little bit inefficient and it is probably possible to do it with only 1 join statement but I can't seem to tackle the issue.
Since this query has to cross reference a lot, really a lot, of records, performance is really an issue here.
With these two nested statements, your UPDATE statements seems quite
inefficient to me. Try this SQL statement below, that should do the job.
SQL Fiddle here: http://sqlfiddle.com/#!2/5825a/2
UPDATE table_A a1
JOIN
(
SELECT a.id as id, max(b.field_B) as max_val
FROM
table_A a
LEFT JOIN table_B b ON a.id = b.reference
GROUP BY a.id
) t on a1.id = t.id
SET
a1.field_A = t.max_val
WHERE
(t.max_val IS NOT NULL)
I have 2 tables. I want to check if columns of table 1 don't have duplicates in columns of table2.
Here is how the search should work!
If no duplicates are found, I want to get the row name from table1.
If I got you right, this is what you want.
SELECT
t1.name
FROM
Table1 t1
WHERE
t1.name
NOT IN
(
SELECT t2.name
FROM Table2 t2
JOIN t1
ON t2.name = t1.name
)
You need to specify a column (or columns) that you will use to "match" the rows, to determine whether they are "duplicates".
I'm going to assume (absent any schema information), that the column name is id.
An "anti-join" pattern is usually the best performing option:
SELECT a.id
FROM table1 a
LEFT
JOIN table2 b
ON a.id = b.id
WHERE b.id IS NULL
(Performance is dependent on a whole bunch of factors.)
Your other options are to use a NOT EXISTS predicate:
SELECT a.id
FROM table1 a
WHERE NOT EXISTS
( SELECT 1
FROM table2 b
WHERE b.id = a.id
)
Or, use a NOT IN predicate:
SELECT a.id
FROM table1 a
WHERE a.id NOT IN
( SELECT b.id
FROM table2 b
WHERE b.id IS NOT NULL
)
The generated execution plan and performance of each of these statements will likely differ. With large sets, the "anti-join" pattern (the first query) usually performs best.
i have a table called users contained
(Table A)
Users
user_id
username
user_type[1,2]
(Table B) if user_type=1
user_id
full_name
(Table C) if user_type=2
user_id
full_name
i want to get single record set by executing single query, is that possible in PHP mysql.
Try this:
SELECT table_a.*, COALESCE(table_b.full_name,table_c.full_name) AS full_name
FROM table_a
LEFT OUTER JOIN table_b ON table_b.user_id = table_a.user_id
LEFT OUTER JOIN table_c ON table_c.user_id = table_a.user_id WHERE 1;
It uses the LEFT OUTER JOIN, which means that it joins it to table_b on the given condition. However, for each row in table_a, whether it finds a matching row in table_b or not, it will return the table_a row. If it does not find a matching row, the table_b columns are just NULL. Same thing with table_c.
Then, we just select all the table_a columns. However, we now have two full_name columns, one from table_b and one from table_c. We use COALESCE to merge them.
COALESCE returns the first non-NULL value.
Since we know that there is either a matching row in table_b or a matching row in table_c, it is not a problem. However, it would be a problem if somehow you allows a matching row to be found in both table_b and table_c.
The risk can be mitigated by adding additional ON clause conditions to get:
SELECT table_a.*, COALESCE(table_b.full_name,table_c.full_name) AS full_name
FROM table_a
LEFT OUTER JOIN table_b
ON table_b.user_id = table_a.user_id AND table_a.user_type = 1
LEFT OUTER JOIN table_c
ON table_c.user_id = table_a.user_id AND table_a.user_type = 2
WHERE 1;
Still, you will need to make sure only 1 row is present for each user in table_b and table_c.
Instead of COALESCE you can optionally use CASE like:
SELECT table_a.*, CASE user_type WHEN 1
THEN table_b.full_name
ELSE table_c.full_name END AS full_name
...
or use an IF function like:
SELECT table_a.*, IF(user_type=1,table_b.full_name,table_c.full_name) AS full_name
...
You can UNION both tables and later on JOIN it with tableA
SELECT a.User_ID,
a.`username`,
b.full_name,
a.user_type
FROM tableA a
(
SELECT user_ID, full_name
FROM tableB
UNION
SELECT user_ID, full_name
FROM tableC
) b ON a.User_ID = b.User_ID
-- WHERE a.user_type = 1 -- add extra condition here
I have two tables with exactly the same fields. Table A contains 7160 records and table B 7130 records.Now I want to insert distinct records from table A into table B such that B should not have any duplicate entry in it. How should I go about doing this?
This basically selects records that are in A that are not in B. It would work, but you might have to tweak the field you use to uniquely identify a record. In this example I used field 'ID' but you might have to change that to A.field1 = B.field1 AND A.field2 = B.field2 etc.
INSERT INTO TABLEB
(
SELECT A.*
FROM TABLEA A
LEFT JOIN TABLEB B ON A.ID = B.ID
WHERE B.ID IS NULL
)
You can use a "union" query to combine the results from multiple tables into a single result set. "union" will only return distinct rows from all tables.
See this page for more info:
http://www.tutorialspoint.com/mysql/mysql-union-keyword.htm
insert into tableB (id)
select t1.id from tableA t1
where t1.id not in (select t2.id from tableB t2)