update field based on another field's updated value - mysql

I have a following query (self-explanatory):
update t
set scans = scans + 1,
is_active = if(count = scans, 0, is_active)
where id = 123
Finally scans get updated and actually equals to count but is_active still stays 1.
I want whenever scans = count to deactivate entry.

That's what should be happening, according to the MySQL documentation:
If you access a column from the table to be updated in an expression, UPDATE uses the current value of the column. For example, the following statement sets col1 to one more than its current value:
UPDATE t1 SET col1 = col1 + 1;
The second assignment in the following statement sets col2 to the current (updated) col1 value, not the original col1 value. The result is that col1 and col2 have the same value. This behavior differs from standard SQL.
UPDATE t1 SET col1 = col1 + 1, col2 = col1;
Single-table UPDATE assignments are generally evaluated from left to right. For multiple-table updates, there is no guarantee that assignments are carried out in any particular order.

Related

Copy value from one column to another and set to NULL - MySQL

In some cases I have to copy values from one column to another and set the first to NULL. This SQL-Statement works as expected:
UPDATE lessons SET order_id_old = order_id, order_id = NULL WHERE id = 1
But I'm not sure if this is a right way to do it so. Or should I better use 2 queries for this purpose?
UPDATE lessons SET order_id_old = order_id WHERE id = 1;
UPDATE lessons SET order_id = NULL WHERE id = 1;
I would definitely go with second approach. Here's what the documentation says:
Single-table UPDATE assignments are generally evaluated from left to
right. For multiple-table updates, there is no guarantee that
assignments are carried out in any particular order.
In your case, it's fine at the moment as there is only one table. However, in future, if someone modifies this statement and adds a new table/join (assuming it'll work fine as it did with one table) it will stop working/give inconsistent results.
So, for the readability/maintainability purpose, go ahead with second approach. (Also, I would recommend wrapping both the update statements into a transaction to preserve atomicity)
From the documentation:
If you access a column from the table to be updated in an expression, UPDATE uses the current value of the column. For example, the following statement sets col1 to one more than its current value:
UPDATE t1 SET col1 = col1 + 1;
The second assignment in the following statement sets col2 to the current (updated) col1 value, not the original col1 value. The result is that col1 and col2 have the same value. This behavior differs from standard SQL.
UPDATE t1 SET col1 = col1 + 1, col2 = col1;
Single-table UPDATE assignments are generally evaluated from left to right. For multiple-table updates, there is no guarantee that assignments are carried out in any particular order.
In your case, it should be fine to use the single statement.

SQL how to use a formula to fill a column like in Excel

My database is in MySQL
I have a table, let's say of 4 columns.
I would like to know if it's possible, and how to implement the following: fill the 4th column according to the value of the column 2 and column 3
In Excel I have a formula, let's give an example: if column2 value is set to "grey" and column3 value is set to "car", then column 4 value should be set to "super"
I just say this as an example.
My real formula in Excel looks like this: =IF(K4=4;"Maximal";IF(K4>4;"Maximal";IF(K4=3;"Important";IF(K4>3;"Important";IF(K4=2;"Limited";IF(K4>2;"Limited";IF(K4=1;"Forgettable";IF(K4>1;"Forgettable";"error"))))))))
However I want to do it in SQL.
I was thinking of creating my table until the column 3, set column 4 to NULL or empty, then open a GUI written in Java and maybe there do a piece of code to automatically fill the column 4 according to what is in column 2 and column 3 (these values will be choosable via Choicelist).
But if there is a way to do it directly in SQL, I am interested
Thx a lot in advance for your help.
regards
Yes. you can easily update your NULL-values according to some requirements for the other values in other columns of a particular row with the Update statement
UPDATE <tablename>
SET <column> = 'value'
WHERE <condition>
The only drawback here might be that you have to create an update statement for each of the combinations of your values in column2 and column3. (however, it's not much work for your amount of conditions).
I created an example (demo):
Creating a table in SQL according to your example could look like this,I used a temporary one for the sake of an example:
CREATE GLOBAL TEMPORARY TABLE demoTable (
"Col1" VARCHAR2(50 BYTE) NOT NULL,
"Col2" VARCHAR2(50 BYTE) NOT NULL,
"Col3" VARCHAR2(50 BYTE) NOT NULL,
"Col4" VARCHAR2(50 BYTE) DEFAULT NULL
)
ON COMMIT PRESERVE ROWS
I also inserted some dummy data:
INSERT INTO demoTable VALUES ('Charles', 'grey', 'car', NULL);
INSERT INTO demoTable VALUES ('Alice', 'grey', 'bike', NULL);
INSERT INTO demoTable VALUES ('Bob', 'red', 'car', NULL);
The result:
Now, create the update statements like this, for example:
UPDATE demoTable dt
SET dt."Col4" = 'super'
WHERE dt."Col2" = 'grey' AND dt."Col3" = 'car';
The result
You can try like this;
select * from mytable
COL1 COL2
---- --------------------
0 -
1 -
2 -
3 -
4 -
4 record(s) selected.
update mytable Set Col2 =
Case
When Col1<1 Then 'error'
When Col1=1 Then 'Forget'
When Col1=2 Then 'Limited'
When Col1=3 Then 'Important'
When Col1=4 Then 'Maximal'
End"
select * from mytable"
COL1 COL2
---- --------------------
0 Error
1 Forget
2 Limited
3 Important
4 Maximal
4 record(s) selected.
You can create a sql function, lets say udfGetColumn4Value taking in the column2, column3 as parameters to it and return a value.
Now you can run a select column2, column3, udfGetColumn4Value(column2, column3) from table or a query as desired. Hope this helps.
You were not very precise regarding which DBMS you're using. And also about the exact logic behind using your two columns.
Still here comes a probable SQL-Server solution, where I have taken one statement using CASE WHEN with your example and concatenated your two columns col2 and col3 (you can apply your further logic of here) otherwise:
UPDATE TableName
SET Col4 = CASE WHEN col2 = 'red' AND col3 = 'car' THEN 'super' ELSE col2 + col3 END;
You should replace col2 + col3 with your further logic.
Seems that a simple UPDATE-Query could address your problem:
update things set result = "super" where thing = "car" and color = "grey";
The where-clause does what you desire to do by saying
fill the column 4 according to what is in column 2 and column 3
I created a test table here on turorialspoint, there you can check if it fits your needs.

How will MySql handle an Update that uses the field-to-be-updated in other parts of the query?

So say I have the following statement:
UPDATE time_tracking_table
SET `end` = NOW(), `duration` = TIME_TO_SEC(TIMEDIFF(`end`,`start`))
WHERE `end` > NOW()
What I am trying to achieve is the following (using 10pm as an example for NOW()): "find all rows where end is later then 10pm, then update end for that row and set it to 10pm, then calculate the difference between the start of that row and it's new value (10pm) as the duration".
I have been testing the above query for a few days and it seems to work. My question is:
a) Is it reliable (or is there some sort of race condition involved here considering the simultaneous update of end and use of end in the where and timediff) and...
b) Even if it does work, is there perhaps a better way to achieve this?
Many thanks in advance for your time and expertise!
From the MySQL docs on UPDATE...
The second assignment in the following statement sets col2 to the
current (updated) col1 value, not the original col1 value. The result
is that col1 and col2 have the same value. This behavior differs from
standard SQL.
UPDATE t1 SET col1 = col1 + 1, col2 = col1;

I want to search and replace multiple values in a table column in one MYsql query

Query to Where X update Y and where A update B in a Mysql Table column.
How can I Do this in MYsql in one query on the same column in a specific table.
I want to search and replace multiple values in a table column.
Conditions in table1 in column1
Where X update Y
and
Where a update b
and
Where 1 update 2
and
Where 3 update 4
and
Where value1 update value 2
And so on.
I can individually do this but how can I do this faster? Is there a mysql function to help me with this?
I have about 120 columns with 200 search and replace/update values for each column.
Thanks.
You can use something like this:
update table table set A = if(conditionA, newA, A), B = if(conditionB, newB, B)
But I expect it will be slower than 2 separate updates, because it is trying to reset every row's value back to itself when it doesn't match the condition.
You could optimise it somewhat by adding:
update table table set A = if(conditionA, newA, A), B = if(conditionB, newB, B)
where conditionA or conditionB
This might be quicker than 2 queries in some circumstances.
You could do something like this:
UPDATE table1
SET
col1 = CASE WHEN col2 THEN a ELSE col1 END,
col3 = CASE WHEN col4 THEN b ELSE col3 END
Note that this sets a value back to itself if the condition fails, effectively causing it to be unchanged.

Is it really no solution to update multiple records in MySQL?

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.