I'm trying to fill a certain column of a SQL table with data from another table. I have a column named "size" in my table which should return the number of rows in the 2nd table where the id of both rows is the same. Is there a way to populate a SQL column based on a certain command? I would love to be able to fill the column based on this command:
SELECT count(*)
FROM second_table
WHERE id = "row_id";
Here is a sample database with the two tables:
Table 1
Name
id
tiger
1
lion
2
gazelle
1
Here is the desired output for Table 2:
id
Number of Animals
1
2
2
1
I am trying to fill the Number of Animals column but do it automatically and dynamically when another row is added or deleted to Table 1, which is why I want the Select count(*) SQL statement as the code for the column.
One method is a correlated subquery:
update table1 t1
set size = (select count(*)
from table2 t2
where t2.id = t1.id
);
If you need to do this dynamically (as data is inserted), then you would need to use a trigger. However, I would suggest that you calculate the value as needed, unless there is a specific reason why you need to store it.
I guess you need something like this:
CREATE TRIGGER UpdateAnimalCountTable2
AFTER INSERT ON `Table1` FOR EACH ROW
begin
DECLARE NewCount int;
SELECT count(1)
INTO #NewCount
FROM Table1
WHERE Table1.id= NEW.id;
UPDATE Table2
SET NoOfAnimals = #NewCount
WHERE id = NEW.id;
END;
Above is the trigger which will be executed after every insert in Table1 and will update the count in Table 2 for ID which just got inserted in Table1.
It's been my first question to this website, I'm sorry if I used any wrong keywords. I have been with one problem from quite a few days.
The Problem is, I have a MYSQL table named property where I wanted to add a ref number which will be a unique 6 digit non incremental number so I alter the table to add a new column named property_ref which has default value as 1.
ALTER TABLE property ADD uniqueIdentifier INT DEFAULT (1) ;
Then I write a script to first generate a number then checking it to db if exist or not and If not exist then update the row with the random number
Here is the snippet I tried,
with cte as (
select subIdentifier, id from (
SELECT id, LPAD(FLOOR(RAND() * (999999 - 100000) + 100000), 6, 0) AS subIdentifier
FROM property as p1
WHERE "subIdentifier" NOT IN (SELECT uniqueIdentifier FROM property as p2)
) as innerTable group by subIdentifier
)
UPDATE property SET uniqueIdentifier = (
select subIdentifier from cte as c where c.id = property.id
) where property.id != ''
this query returns a set of record for almost all the rows but I have a table of entries of total 20000,
but this query fills up for ~19000 and rest of the rows are null.
here is a current output
[current result picture]
If anyone can help, I am extremely thanks for that.
Thanks
Instead of trying to randomly generate unique numbers that do not exist in the table, I would try the approach of randomly generating numbers using the ID column as a seed; as long as the ID number is unique, the new number will be unique as well. This is not technically fully "random" but it may be sufficient for your needs.
https://www.db-fiddle.com/f/iqMPDK8AmdvAoTbon1Yn6J/1
update Property set
UniqueIdentifier = round(rand(id)*1000000)
where UniqueIdentifier is null
SELECT id, round(rand(id)*1000000) as UniqueIdentifier FROM test;
How can I store only 10 rows in a MySQL table? The older rows should be deleted when a new row is added but only once the table has 10 rows.
Please help me
You could achieve this with an after insert trigger, delete the row where it is min date. e.g. DELETE FROM myTable WHERE myTimestamp = (SELECT MIN(myTimestamp) FROM myTable) but that could in theory delete multiple rows, depending on the granularity of your updates.
You could have an incrementing sequence, and always just delete the min of that sequence.
The question is why you'd want to do this though? It's a slightly unusual requirement.
A basic example (not validated/executed, I don't have mySQL on this particular machine) would look something like.
CREATE TRIGGER CycleOldPasswords AFTER INSERT ON UserPasswords FOR EACH ROW
set #mycount = SELECT COUNT(*) FROM UserPasswords up where up.UserId = NEW.UserId;
if myCount >= 10 THEN
DELETE FROM UserPasswords up where up.Timestamp = (SELECT min(upa Timestamp) FROM UserPasswords upa WHERE NEW.UserId = upa.UserId) AND NEW.UserId = up.UserId;
END
END;
You can retrieve the last inserted id when your first row is inserted, and store it in a variable. When 10 rows are inserted, delete the row having id < id of the first inserted record. Please try it.
first of all insert all values using your insert query
and then run this query
delete from table_name where (cond) order by id desc limit 10
must specify an id or time in one column
I have a simple query that increases the value of a field by 1.
Now I used to loop over all id's and fire a query for each of them, but now that things are getting a bit resource heavy I wanted to optimize this. Normally I would just do
UPDATE table SET field = field + 1 WHERE id IN (all the ids here)
but now I have the problem that there are id's that occur twice (or more, I can't know that on forehand).
Is there a way to have the query run twice for id 4 if the query looks like this:
UPDATE table SET field = field + 1 WHERE id IN (1, 2, 3, 4, 4, 5)
Thanks,
lordstyx
Edit: sorry for not being clear enough.
The id here is an auto inc field, so it are all unique ID's. the id's that have to be updated are indirectly comming from users, so I can't predict which id is going to occur how often.
If there are the ID's (1, 2, 3, 4, 4, 5) I need the field of row with id 4 to be incremented with 2, and all the rest with 1.
If (1, 2, 3, 4, 4, 5) comes from a SELECT id ... query, then you can do something like this:
UPDATE yourTable
JOIN
( SELECT id
, COUNT(id) AS counter
....
GROUP BY id
) AS data
ON yourTable.id = data.id
SET yourTable.field = yourTable.field + data.counter
;
Since the input comes from users, perhaps you can manipulate it a bit. Change (1, 2, 3, 4, 4, 5) to (1), (2), (3), (4), (4), (5).
Then (having created a temporary table):
CREATE TABLE tempUpdate
( id INT )
;
Do the following procedure:
add the values in the temporary table,
run the update and
delete the values.
Code:
INSERT INTO TempUpdate
VALUES (1), (2), (3), (4), (4), (5)
;
UPDATE yourTable
JOIN
( SELECT id
, COUNT(id) AS counter
FROM TempUpdate
GROUP BY id
) AS data
ON yourTable.id = data.id
SET yourTable.field = yourTable.field + data.counter
;
DELETE FROM TempUpdate
;
No. But you could perform something like
UPDATE table
SET field = field + (LENGTH(',1,2,3,4,4,5,') - LENGTH(REPLACE(',1,2,3,4,4,5,', CONCAT(',', id, ','), ''))) / LENGTH(CONCAT(',', id, ','))
WHERE id IN (1, 2, 3, 4, 4, 5)
if you need row with id = 4 specifically to be incremented twice
Here is solution you wanted, but I'm not sure this is what you need.
Let's say that your talbe is called test. You want to increase id. I've added a field idwas to easily show what was the id before the query:
CREATE TABLE `test` (
`id` int(10) unsigned NOT NULL auto_increment,
`idwas` int(8) unsigned default NULL,
PRIMARY KEY (`id`)
) ;
Let's fill it with data:
truncate table test;
insert into test(id) VALUES(1),(3),(15);
update test set idwas = id;
Now let's say that you have user input 1,3,5,3, so:
id 1 should be increased by 1
id 3 should be increased by 2
id 5 is missing, nothing to increase.
row with id 15 should not be changed because not in user input
We'll put the user input in a variable to be easier to use it:
SET #userInput = '1,3,5,3';
then do the magic:
SET #helperTable = CONCAT(
'SELECT us.id, count(us.id) as i FROM ',
'(SELECT ',REPLACE(#userInput, ',',' AS `id` UNION ALL SELECT '),
') AS us GROUP BY us.id');
SET #stmtText = CONCAT(
' UPDATE ',
'(',#helperTable,') AS h INNER JOIN test as t ON t.id = h.id',
' SET t.id = t.id + h.i');
PREPARE stmt FROM #stmtText;
EXECUTE stmt;
And this is the result:
mysql> SELECT * FROM test;
+----+-------+
| id | idwas |
+----+-------+
| 2 | 1 |
| 5 | 3 |
| 15 | 15 |
+----+-------+
3 rows in set (0.00 sec)
If it's reasonable, you could try doing a combination of what you had before and what you have now.
In whatever is creating this list, separate it into (depending on the language's constructs) some type of array. Follow this by sorting it,finding how many multiples of each there are, and doing whatever else you need to to get the following: an array with (increment-number => list of ids), so you do one query for each increment amount. Thus, your example becomes
UPDATE table SET field = field + 1 WHERE id IN (1, 2, 3, 5)
UPDATE table SET field = field + 2 WHERE id IN (4)
In php, for example, I would take the array, sort the array, use the content of the array as the keys for another array of the form (id => count), and then fold that over into the (count => list of ids) array.
It's not that efficient, but is definitely better than one query per id. It's also probably better than using iteration and string manipulation in SQL. Unless you're forced to use SQL to do everything (which it sounds like you're not), I wouldn't use it to do everything, when it's overly awkward to do so.
You could use the following:
create temporary table temp1 (id integer);
insert into temp1 (id) values (1),(2),(3),(4),(4),(5);
update your_table set your_field = your_field + (select count(*) from temp1 where id = your_table.id)
This solution requires you to format the id list like (1),(2),(3),(4),(4),(5) but I don't think that is a problem, right?
This worked on my test database, hope it works for you too!
Regards,
Arthur
I want to do all these update in one statement.
update table set ts=ts_1 where id=1
update table set ts=ts_2 where id=2
...
update table set ts=ts_n where id=n
Is it?
Use this:
UPDATE `table` SET `ts`=CONCAT('ts_', `id`);
Yes you can but that would require a table (if only virtual/temporary), where you's store the id + ts value pairs, and then run an UPDATE with the FROM syntax.
Assuming tmpList is a table with an id and a ts_value column, filled with the pairs of id value, ts value you wish to apply.
UPDATE table, tmpList
SET table.ts = tmpList.ts_value
WHERE table.id = tmpList.id
-- AND table.id IN (1, 2, 3, .. n)
-- above "AND" is only needed if somehow you wish to limit it, i.e
-- if tmpTbl has more idsthan you wish to update
A possibly table-less (but similar) approach would involve a CASE statement, as in:
UPDATE table
SET ts = CASE id
WHEN 1 THEN 'ts_1'
WHEN 2 THEN 'ts_2'
-- ..
WHEN n THEN 'ts_n'
END
WHERE id in (1, 2, ... n) -- here this is necessary I believe
Well, without knowing what data, I'm not sure whether the answer is yes or no.
It certainly is possible to update multiple rows at once:
update table table1 set field1='value' where field2='bar'
This will update every row in table2 whose field2 value is 'bar'.
update table1 set field1='value' where field2 in (1, 2, 3, 4)
This will update every row in the table whose field2 value is 1, 2, 3 or 4.
update table1 set field1='value' where field2 > 5
This will update every row in the table whose field2 value is greater than 5.
update table1 set field1=concat('value', id)
This will update every row in the table, setting the field1 value to 'value' plus the value of that row's id field.
You could do it with a case statement, but it wouldn't be pretty:
UPDATE table
SET ts = CASE id WHEN 1 THEN ts_1 WHEN 2 THEN ts_2 ... WHEN n THEN ts_n END
I think that you should expand the context of the problem. Why do you want/need all the updates to be done in one statement? What benefit does that give you? Perhaps there's another way to get that benefit.
Presumably you are interacting with sql via some code, so certainly you can simply make sure that the three updates all happen atomically by creating a function that performs all three of the updates.
e.g. pseudocode:
function update_all_three(val){
// all the updates in one function
}
The difference between a single function update and some kind of update that performs multiple updates at once is probably not a very useful distinction.
generate the statements:
select concat('update table set ts = ts_', id, ' where id = ', id, '; ')
from table
or generate the case conditions, then connect it to your update statement:
select concat('when ', id, ' then ts_', id) from table
You can use INSERT ... ON DUPLICATE KEY UPDATE. See this quesion: Multiple Updates in MySQL
ts_1, ts_2, ts_3, etc. are different fields on the same table? There's no way to do that with a single statement.