MySQL update column which is a value in another column - mysql

This is my previous question related to the my query.
MySQL select column which is a value in another column
The problem is that want to do operations on the values extracted and store it back into the original db. I've tried using a update & case but am not able to achieve it.
update msisdn_table
CASE reason
WHEN 'NoAnswer' THEN (case when (NoAnswer>0) then update msisdn_table set NoAnswer = NoAnswer-1 end)
WHEN 'NetworkBusy' THEN (case when NetworkBusy>0 then update msisdn_table set NetworkBusy = NetworkBusy-1 end)
WHEN 'CallRejection' THEN (case when CallRejection>0 then update msisdn_table set CallRejection = CallRejection-1 end)
WHEN 'Unavailable' THEN (case when Unavailable>0 then update msisdn_table set Unavailable = Unavailable-1 end)
END
Any help?

Try it this way if you want to do it one statement
UPDATE msisdn_table
SET NoAnswer = IFNULL(IF(reason = 'NoAnswer',
NULLIF(NoAnswer, 0) - 1, NoAnswer), 0),
NetworkBusy = IFNULL(IF(reason = 'NetworkBusy',
NULLIF(NetworkBusy, 0) - 1, NetworkBusy), 0),
CallRejection = IFNULL(IF(reason = 'CallRejection',
NULLIF(CallRejection, 0) - 1, CallRejection), 0),
Unavailable = IFNULL(IF(reason = 'Unavailable',
NULLIF(Unavailable, 0) - 1, Unavailable), 0)
WHERE reason IN('NoAnswer', 'NetworkBusy', 'CallRejection', 'Unavailable');
Note:
I changed CASE with less verbose IF(), although if you like it better you can use it the same way.
This approach has one possible side effect as it always updates the column(s) either with a new or with old value. It may matter if for example you have a trigger defined on the table.
You want to apply a WHERE clause to make sure that rows with other reason codes are not affected
Here is SQLFiddle demo

update msisdn_table set NoAnswer = NoAnswer-1 where (NoAnswer>0) ;
update msisdn_table set NetworkBusy = NetworkBusy-1 where (NetworkBusy = NetworkBusy-1) ;
update msisdn_table set CallRejection = CallRejection-1 where (CallRejection>0) ;
update msisdn_table set 'Unavailable' = 'Unavailable'-1 where (Unavailable>0) ;

Related

Select Case / Update one field based on another

Basically, I am trying to cleanse a database and have all file paths point to sample documents. I am reading from one column (extension), and then updating another column (filename) and making a change based on the extension. I also want a catch all. For example, if extension is DOC, then make the path "sample.doc"; if the extension is PDF, then make the path "sample.pdf", if unknown, then make the path "sample.txt".
I have this code working, but think it would be better served with a select/case loop:
select * from dbo.tsrecelec
UPDATE dbo.TSRECELEC
SET dbo.tsrecelec.reSID = '00+SampleWord.doc'
WHERE dbo.tsrecelec.reExtension = 'DOC'
UPDATE dbo.TSRECELEC
SET dbo.tsrecelec.reSID = '00+SampleWord.docx'
WHERE dbo.tsrecelec.reExtension = 'DOCX'
UPDATE dbo.TSRECELEC
SET dbo.tsrecelec.reSID = '00+SampleADOBE.pdf'
WHERE dbo.tsrecelec.reExtension = 'PDF'
In my NONE SQL brain, I was thinking something like this might work?
SELECT reSID, reExtension,
CASE
WHEN reExtension = 'DOC' THEN SET reSID = '00+SampleWord.doc'
WHEN dbo.tsrecelec.reExtension = 'DOCX' THEN SET dbo.tsrecelec.reSID = '00+SampleWord.docx'
ELSE dbo.tsrecelec.reSID = '00+SampleFile.txt'
END
FROM dbo.tsrecelec;
Any and all help is appreciated!
Three updates is fine, but you can phrase this as:
UPDATE dbo.TSRECELEC
SET reSID = (CASE WHEN reExtension = 'DOC'
THEN '00+SampleWord.doc'
WHEN reExtension = 'DOCX'
THEN '00+SampleWord.docx'
WHEN reExtension = 'PDF'
THEN '00+SampleADOBE.pdf'
END)
WHERE reExtension IN ('DOC', 'DOCX, 'PDF');
Try to use CASE...WHEN...THEN.... It's more performant if you are getting more extensions in the future:
UPDATE yourtable
SET col1 = (CASE WHEN col2 = 'extension you want'
THEN 'nameofyourfile.extension'
WHEN ...
THEN ...
END)
WHERE col2 IN ('extension1', 'extension2', 'extension3','...');

How to update a record conditionally with a field value in the same record in MySQL? [duplicate]

I would like to do the following.
Update a field based on the value of another field like
update table set if(fielda=1){fieldb=2 fieldc=3}else{fieldd=2 fielde=3}
I know this is not valid mysql but its the best way for me to describe the problem.
update table set
b = case when a = 1 then 2 else b end,
c = case when a = 1 then 3 else c end,
d = case when a = 1 then d else 2 end,
e = case when a = 1 then e else 3 end
edit
according to your comment try this:
update table set
datefield_a = case when field_a = 1 then now() else datefield_a end,
datefield_b = case when field_a <> 1 then now() else datefield_b end
I think this syntax will achieve the result you attempted to specify.
UPDATE mytable
SET fieldb = CASE WHEN fielda = 1 THEN 2 ELSE fieldb END
, fieldc = CASE WHEN fielda = 1 THEN 3 ELSE fieldc END
, fieldd = CASE WHEN fielda = 1 THEN fieldd ELSE 2 END
, fielde = CASE WHEN fielda = 1 THEN fielde ELSE 3 END
The "trick" here is that we are updating all four columns, but in some "cases", we are assigning the current value of the column back to the column, resulting in no real change to the column value. (Once you get your mind bent around that idea, it's pretty easy.)
With MySQL, we do have a handy IF function (not available in most other RDBMS) that we can use to abbreviate that a bit, and achieve the same thing:
UPDATE mytable
SET fieldb = IF(fielda = 1, 2, fieldb)
, fieldc = IF(fielda = 1, 3, fieldc)
, fieldd = IF(fielda = 1, fieldd, 2)
, fielde = IF(fielda = 1, fielde, 3)
The pain is that you still have to repeat that same conditional test multiple times.
A single scan through the table (like these statements do), and getting all those assignments done in one fell swoop is going to be faster (and more efficient) than breaking this up and doing the assignments piecemeal using multiple statements.

MERGE statement with two WHEN MATCHED

I have this MERGE statement working fine:
MERGE INTO product_replenishment PR
USING ( SELECT * FROM traxs_temp..__MinMaxImport WHERE session_id = #session_id ) T
ON T._product = PR.product AND T._branch_no = PR.branch_no
WHEN MATCHED AND T._stock_warehouse IS NOT NULL THEN
UPDATE SET
date_time_updated = GETDATE(),
user_no_updated = #user_no,
stock_warehouse = T._stock_warehouse
WHEN NOT MATCHED BY TARGET AND T._stock_warehouse IS NOT NULL THEN
INSERT
(date_time_created,
date_time_updated,
user_no_created,
user_no_updated,
branch_no,
product,
stock_warehouse,
archive)
VALUES
(GETDATE(),
GETDATE(),
#user_no,
#user_no,
T._branch_no,
T._product,
T._stock_warehouse,
0);
I want to add another WHEN MATCHED statement like this:
WHEN MATCHED AND T._stock_warehouse IS NOT NULL THEN
UPDATE SET
date_time_updated = GETDATE(),
user_no_updated = #user_no,
stock_warehouse = T._stock_warehouse
WHEN MATCHED AND T._stock_warehouse IS NULL THEN
UPDATE SET
date_time_updated = GETDATE(),
user_no_updated = #user_no,
archive = 1
But I get an error: An action of type 'WHEN MATCHED' cannot appear more than once in a 'UPDATE' clause of a MERGE statement.
Is it impossible to achieve what I'm trying to do?
The general case can be emulated using CASE expressions as I've shown in this answer here, or in this blog post here. But your case is more specific, because the difference between the two clauses is simpler than the general case. You can combine them into one clause:
WHEN MATCHED THEN UPDATE SET
-- These are always updated the same way, regardless of the WHEN MATCHED AND predicate
date_time_updated = GETDATE(),
user_no_updated = #user_no,
-- These depend on the relevant WHEN MATCHED AND predicate, so use CASE
stock_warehouse = CASE
WHEN T._stock_warehouse IS NOT NULL THEN T._stock_warehouse
ELSE stock_warehouse
END,
archive = CASE WHEN T._stock_warehouse IS NULL THEN 1 ELSE archive END

Update Same mysql field twice in single query

I am not sure if its possible or not, Just want to know if it is. I have column plan_popular which has default value 0. Lets same i have a list :
Plan Name | plan_popular | amount
===================================
plan A 0 25.00
plan B 1 50.00
plan C 0 90.00
This is how i am doing:
$stmt = "update {CI}plans set plan_popular = 0";
$this->db->query($stmt);
$stmt2 = "update {CI}plans set plan_popular = 1 where plan_id = ?";
$this->db->query( $stmt2, array($plan_id) );
Now i have set the plan C to make. Now i want to reset it and want to make popular plan C to 1. What i am doing is running two queries, One i reset and make the plan_popular 0 and the second is get the update the plan C to 1 with there id. Is it possible in single query?
You can use an expression to determine the value to assign:
UPDATE {CI}plans
SET plan_popular = IF(plan_id = ?, 1, 0);
try this,
UPDATE {CI}plans
SET `plan_popular` = CASE `Plan Name`
WHEN 'plan C' THEN 1
ELSE 0
END
WHERE `Plan Name` IN((select `Plan Name` from {CI}plans where plan_popular=1 ) , 'plan C');
Updates can be expensive, what with manipulating locks, triggers and constraints firing, etc. In general, you want to avoid updating a field to the same value it already has. In English, if plan_id = variable and plan_popular is 0 then set it to 1 but if plan_id is any other value and plan_popular is 1 then set it to 0.
UPDATE {CI}Plans
SET plan_popular = if( plan_id = ?, 1, 0 )
where (plan_id = ? and plan_popular = 0)
or (plan_id <> ? and plan_popular = 1);
The where clause lets through only those rows that will actually be changed by the update. If this is a largish table, that can make quite a difference in response time. Logic is much less expensive than any actual operation that can performed in the database.

Possible to change these 2 SQL queries into 1?

Is it possible to change these 2 queries into 1?
Query #1:
UPDATE `pvdownloader`.`posts`
SET `exists` = 'y'
WHERE source = ANY (SELECT source FROM dbdownloader.posts)
AND `mangacount` = 0
AND NOT `exists` = 'm'
Query #2:
UPDATE `pvdownloader`.`posts`
SET `exists` = 'n'
WHERE `exists` = 'u'
AND `mangacount` = 0
I'm assuming it would be possible to make something like this with IF/ELSE but I can't figure out how to use it at all :<
Maybe something like this would work:
update
pvdownloader.posts
set
exists =
case
when source = any(select source from dbdownloader.posts) and mangacount = 0 and exists != 'm' then 'y'
when exists = 'u' and mangacount = 0 then 'n'
end
where
(source = any(select source from dbdownloader.posts) and mangacount = 0 and exists != 'm')
or
(exists = 'u' and mangacount = 0)
;
As #MostyMostacho suggested, I took the liberty of changing your logic to not have a double-negative.