I'm normalizing an existing database. I currently have two columns in Table1, domain and container, with limited distinct combinations (currently ~30 combinations of these two from ~1000 records). I've built a new Table2 that holds all combinations, with a primary key (container_id) auto-generated when a new record is installed. I've added a container_id column to Table1, and want to fill in the values based on the Table1.container column.
At this point, all of the container names in table 2 are distinct, but that could change in the future, hence the need for a unique number as the PK.
i.e.
UPDATE Table1
SET container_id = (SELECT Table2.container_id
FROM Table2
WHERE Table2.container = Table1.container)
WHERE EXISTS
( SELECT Table2.container_id
FROM Table2
WHERE Table2.container = Table1.container)
This query return error 1242: subquery returns more than one row.
Am I barking up the totally wrong tree? Table2 should have zero duplicate values.
I should have used a join to update the table1
UPDATE Table1
LEFT JOIN Table2 USING (container)
SET Table1.contanier_id = Table2.contanier_id
WHERE Table1.contanier_id IS NULL AND Table2.contanier_id IS NOT NULL;
Table2.container is not unique, hence can get repeated. Due to this both sub queries return more than one row.
Related
I have been trying for about 8 hours now and to no avail. I am trying to update or insert the AVG of 2 to 10 rows from a single column into another table.
The code I use right now to calculate the average.
SELECT COUNT(*), NAME, AVG(AVERAGE) FROM table1 GROUP BY NAME ORDER BY NAME;
This returns the proper results as I used group by as a workaround but now I need to get that data into another table.
However when I try to run update or insert mysql always complains about a multi line subquery return.
How can I get this into table2 where the name matches and into column average of table2? The name is 100% unique. I also would like the names to match. This will be updated maybe once a day.
EDIT:
First table ENTRY_ID, NAME(not unique for multiple entries), AVERAGE
Second table has ID(unique), NAME(unique), AVERAGE
I have tried so many queries its not funny I've searched all the documentation I'm just not putting something together right.
When you run the above it might have 8 rows it runs AVG(AVERAGE) maybe 6 they are matched by name.
I want to store them in table2 where the name in table1 matches the name in table2 but just gives the single average of the above query.
Thanks
EDIT2: This is the code that worked
INSERT INTO table2 (NAME, AVERAGE)
(SELECT * FROM
(SELECT NAME, AVG(AVERAGE) as AVERAGE
FROM table1
GROUP BY NAME) main_query)
ON DUPLICATE KEY
UPDATE table2.AVERAGE = main_query.AVERAGE;
Thanks to #ARubiksCube
I am unsure of what your actual error message is. My guess is that you are using a newer version of MYSQL so you are getting this error.
This query will update all the records in table2 with the values from table1. If the record does not exist, it will be inserted. If the record exists, It will be updated.
INSERT INTO table2 (NAME, AVERAGE)
SELECT *
FROM
(SELECT NAME, AVG(AVERAGE) as AVERAGE
FROM table1
GROUP BY NAME) main_query
ON DUPLICATE KEY
UPDATE table2.AVERAGE = main_query.AVERAGE;
I have two questions which if someone can help me it would be great and would be a great learning for me.
I have two tables and my requirement is to update a column A of
Table 1 value only for those rows for which the column B has
values same as column B of Table2.
I am looking for an optimized query for this in SQL.
UPDATE DBA.COM, DBA.MEN
SET DBA.COM.ND_MAN=''
WHERE DBA.MEN
After this, I couldn't select column names in where condition.
The problem I am finding in Column B of both the tables is, it is
unique identified (GUID) from the UI. So, when I copy the cell value
from "SQL Anywhere" Interactive SQL Editor, it displays the column
value copied as follows:
0x99e2f2a23f9946acb0ceb374a627b142
and not as 99e2f2a23f9946acb0ceb374a627b142.
However, both the table's column value when I copy, it is starting
with 0x. So will it not pose any problem I guess?
Or how to rectify it in above query which you will create for question 1?
You need to join and update something as
update table1 t1
join table2 t2 on t1.B = t2.B
set t1.A = 'some value'
Answer to your first question
UPDATE t1, t2 SET t1.name = new_value WHERE t1.id = t2.id;
Notes:
A multiple-table UPDATE is an extension of a single-table statement:
Following the UPDATE keyword, name the tables involved in the operation, separated by
commas. (You must name all the tables used in the query, even if you aren’t updating all
of them.)
In the WHERE clause, describe the conditions that determine how to match records in the
tables.
In the SET clause, assign values to the columns to be updated. These assignments can
refer to columns from any of the joined tables.
Let's say I have 5 MyISAM tables in my database. Each table has a key, let's call it "id_num" ...
"id_num" is the field which I use to connect all the tables together. A certain value of "id_num" may appear in all tables or sometimes only a subset of the tables.
If I want to delete all instances of a certain "id_num" in the database, can I just make a DELETE command on all tables or should I check to see if that value for "id_num" exists?
DELETE * FROM table1 WHERE id_num = 123;
DELETE * FROM table2 WHERE id_num = 123;
DELETE * FROM table3 WHERE id_num = 123;
DELETE * FROM table4 WHERE id_num = 123;
DELETE * FROM table5 WHERE id_num = 123;
Or should I perform a SELECT command first on each table to check if these rows exist in the table before deletion? What is best practice?
(I am using MyISAM so cascading delete is not an option here.)
To answer your question about first running SELECT, there's no advantage to doing so. If there's no row in a given table, then the DELETE will simply affect zero rows. If there are matching rows, then doing the SELECT first and then the DELETE would just be doing double the work of finding the rows. So just do the DELETE and get it over with.
Are you aware that MySQL has multi-table DELETE syntax?
If you are certain that table1 has a matching row, you can use outer joins for the others:
DELETE table1.*, table2.*, table3.*, table4.*, table5.*
FROM table1
LEFT OUTER JOIN table2 USING (id_num)
LEFT OUTER JOIN table3 USING (id_num)
LEFT OUTER JOIN table4 USING (id_num)
LEFT OUTER JOIN table5 USING (id_num)
WHERE table1.idnum = 123;
I'm assuming id_num is indexed in all these tables, otherwise doing the JOIN will perform poorly. But doing the DELETE without the aid of an index to find the rows would perform poorly too.
Sounds like you need to change your design as follows - have a table with id_num as a PK and make id_num a FK in the other tables, with on-delete-cascade. This will allow you to only run a single delete statement to delete all applicable data (and this is also generally the more correct way of doing things).
The above apparently doesn't work in MyISAM, but there is a workaround using triggers (but now it does seem like a less appealing option).
But I believe your above queries should work, no need to check if something exists first, DELETE will just not do anything.
Most APIs provide you with some sort of rows affected count if you'd like to see whether data was actually deleted.
You should not execute select query before deleting from the table. As select query will put some extra load to the server. However after executing delete query you can check how many rows has been deleted using mysql_affected_rows() function in php.
MySQL noob here; looked around first but couldn't find the answer to this question.
So I have two tables in MySQL, one (Table1) which consists of one column containing unique list of names (Col1) and another containing corresponding binary values (Col2). The second table (Table2) contains a list of recurring names with a empty column waiting to be filled with binary values from the first table. What I want to do is, for each instance of a recurring name in Table2, insert the binary value from Col2 associated with the matching unique name in Table1.
I know how to do this in Excel—you just place the following VLOOKUP statement next to every row containing a recurring name. In the following code snippet A2 is a recurring name, unique names are contained in column B, and the binary values are contained in column C.
=VLOOKUP(A2,$B$2:$C$106095,2,FALSE)
But I can't for the life of me figure out how to reproduce this effect in MySQL. I can't use Excel because there's too much data. Anyone have any ideas? Thanks in advance!
I think that you want something like this (I don't know what the Excel statement does):
UPDATE table2 JOIN table1 ON table1.col1 = table2.col1
SET table2.col2 = table2.col2
WHERE table2.col2 IS NULL
This will update each row table2 that has col2 empty, searching for the corresponding row in table1 based on matching col1 columns.
Btw, do you have a reason to do this? Why not just join both tables when selecting the data? For example:
SELECT table2.col1, table1.col2
FROM table2 JOIN table1 ON table1.col1 = table2.col1
I have 2 Innodb tables. IN TableA I have a column (guidNew) that I want to assign its' values to a column in TableB (owner) depending on the relation between the column in TableA (guid) and TableB (owner).
Basically Tabl6eB (owner) has multiple entries that correspond to one TableA (guid). This is a Many to One relation. I want to change the TableB(owner) value to the new TableA(guidNew) values.
This is an example of the query:
UPDATE `TableB`, `TableA`
SET
`TableB`.`owner` = `TableA`.`guidNew`
WHERE `TableB`.`guid` != 0
AND `TableB`.`owner` = `TableA`.`guid`;
Now I do not know if this is working or not because there are more than 2 million entries. Is there a way to know the progress it has AND more important, a way to do it faster.
Make sure that you have indexed the guid and owner columns.
Try using the EXPLAIN command to see how the query is being performed
EXPLAIN SELECT TableB.owner, TableA.guidNew
FROM TableB, TableA
WHERE TableB.guid != 0
AND TableB.owner = TableA.guid