MySQL CASE...WHERE...THEN statements - mysql

I have a MySQL UPDATE statement that uses a CASE clause
UPDATE partsList SET quantity =
CASE
WHEN partFK = 1 THEN 4
WHEN partFK = 2 THEN 8
END
WHERE buildFK = 1;
The above statement works. Yet when I remove one of the WHEN statements, it breaks and the error indicates the CASE clause isn't returning anything. Is it that the CASE clause must have more than one WHEN to function.
I don't know beforehand how many updates I'll need, so I'm trying to build a single update statement that can handle one or many updates.
Thanks for any insights you can provide.

It isn't that the CASE must have more than one, WHEN...THEN, it's that it must handle all the data you give it.
If you removed one of the clauses, you leave a hole. e.g.
UPDATE partsList SET quantity =
CASE
WHEN partFK = 1 THEN 4
END
WHERE buildFK = 1;
With this update statement, if parkFK is 2, then the update fails because the CASE can't handle the input.
You can either limit your source data by adding another line to your where-clause (e.g. AND partFK in (1,2)), or you could add an ELSE to the case expression.
UPDATE partsList SET quantity =
CASE
WHEN partFK = 1 THEN 4
WHEN partFK = 2 THEN 8
ELSE 12
END
WHERE buildFK = 1;
However, based on the SQL statement you've shown, there is probably a better way. Presumably, partFK is a foreign-key to some other table. Can you pull the value for quantity from there?

Add ELSE NULL or something before the END of the case. See http://dev.mysql.com/doc/refman/5.0/en/case-statement.html for more info.

MS SQL Server version of sql statement would be as following:
Update partsList SET quantity =
CASE partFK
WHEN 1 THEN 4
WHEN 2 THEN 8
END

Related

MySQL Case not working in MySQL update query

I am new in Web Development and now I am working on chat tasks.
I have message table to save conversation between two users.
Now I want to delete single message if one user delete it but this message will be visible to second user until second user delete the message for this I have two columns to manage delete criteria but when I run my sql query then it gives me true but db column not updated. Default values of the column is 0 (zero). Below is my sql query that I am using.
UPDATE messages
SET delete_two = CASE WHEN delete_one > 0 THEN 9600 ELSE delete_two END,
delete_one = COALESCE(delete_one,9600)
WHERE id = 367
Anyone help please to solve this issue.
Thanks in advance
COALESCE works on null and not null values. If you want to compare with 0 then you need to use IF, e.g.:
UPDATE messages
SET delete_two = CASE WHEN delete_one > 0 THEN 9600 ELSE delete_two END,
delete_one = IF(delete_one = 0 , 9600, delete_one)
WHERE id = 367
Here's the SQL Fiddle.
Default (0) has nothing to do with the update statement. I can't understand the logic in that query...
First of all, I am not sure true usage of these columns. What are the possible values there? Is that just the indicator if the row is updated or not? Then I can't understand why do you use 9600 as the default value in COALESCE. Why not 1?
Another thing I can't understand how can that happen that you update the message for 2 users in 1 update statement? How can that logically happen?
Now let's comeback to your query, if you still need to update then:
UPDATE messages
SET delete_two = CASE WHEN delete_one > 0 THEN 9600 ELSE delete_two END,
delete_one = CASE WHEN delete_one = 0 OR delete_one IS NULL THEN 9600 ELSE delete_one END
WHERE id = 367
I've added checking for delete_one IS NULL because you are still able insert NULL to that column (of course if it is nullable) even if there is DEFAULT constraint.

Pin/Flag a record in a mysql table to true and the rest to false in a single statement

Address Table with 50 records. Has a bool field called "primary_address_indicator".
I want to update a selected record to true and automatically set all other 49 records to false.
I know I can do this with 2 sql statements
First (update all records to false)
UPDATE address SET address.primary_address_indicator=0
Then (update specific record to true)
UPDATE address SET address.primary_address_indicator=1 WHERE address.record_id=31
Is there a way to do this in a single sql statement? Something like #Rank?
Keeping it simple... no Unions or some weird self table join.
Maybe what I am looking for does not exist...and that is fine too. just curious.
Update with Case
UPDATE tableName
SET Pin = CASE
WHEN 1=1 --'your condition'
THEN True
ELSE False
END
PC : #keWalker
The simplest way is simply to treat the boolean result as a number:
UPDATE address a
SET a.primary_address_indicator = (a.record_id = 31);
CASE is the formal way to do it. This short-hand is specific to MySQL but it is one of the database-specific features that I like.

Need help in writing Efficient SQL query

I have the following query, written inside perl script:
insert into #temp_table
select distinct bv.port,bv.sip,avg(bv.bv) bv, isnull(avg(bv.book_sum),0) book_sum,
avg(bv.book_tot) book_tot,
check_null = case when bv.book_sum = null then 0 else 1 end
from table_bv bv, table_group pge, table_master sm
where pge.a_p_g = '$val'
and pge.p_c = bv.port
and bv.r = '$r'
and bv.effective_date = '$date'
and sm.sip = bv.sip
query continued -- need help below (can some one help me make this efficient, or rewriting, I am thinking its wrong)
and ((sm.s_g = 'FE')OR(sm.s_g='CH')OR(sm.s_g='FX')
OR(sm.s_g='SH')OR(sm.s_g='FD')OR(sm.s_g='EY')
OR ((sm.s_t = 'TA' OR sm.s_t='ON')))
query continued below
group by bv.port,bv.sip
query ends
explanation: some $val that contain sip with
s_g ('FE','CH','FX','SH','FD','EY') and
s_t ('TA','ON') have book_sum as null. The temp_table does not take null values,
hence I am inserting them as zero ( isnull(avg(bv.book_sum),0) ) where ever it encounters a null for the following s_g and s_m ONLY.
I have tried making the query as follows but it made my script to stop wroking:
and sm.s_g in ('FE', 'CH','FX','SH','FD','EY')
or sm.s_t in ('TA','ON')`
I know this should be a comment, but I don't have the rep. To me, it looks like it's hanging because you lost your grouping at the end. I think it should be:
and (
sm.s_g in ('FE', 'CH','FX','SH','FD','EY')
or
sm.s_t in ('TA','ON')
)
Note the parentheses. Otherwise, you're asking for all of the earlier conditions, OR that sm.s_t is one of TA or ON, which is a much larger set than you're anticipating, which may cause it to spin.

MySQL UPDATE - SET field in column to 1, all other fields to 0, with one query

I am updating a field in a mysql column namend "frontpage", set it from 0 to 1.
No problem with this query:
mysql_query("UPDATE table SET frontpage='1' WHERE user_id='999' AND poll_id='555'");
What I'd like to accomplish is, in case user_id 999 got already other existing poll_id's set to 1 in the past, these rows should be set to 0 automatically.
As a beginner learning MySQL, I would run 2 queries, first one to set everything to frontpage='0' WHERE user_id='999' and the second query to set frontpage='1' WHERE user_id='999' AND poll_id='555'.
My question now is, could this be done by using only one query, and how?
PS: Not sure if it has something to do with my question, I've read these answers MySQL: Updating all rows setting a field to 0, but setting one row's field to 1 but I haven't really understood the logic, perhaps someone can explain it to a mysql beginner please.
I think you want this logic:
UPDATE table
SET frontpage = (case when poll_id = '555' then '1' else '0' end)
WHERE user_id = '999';
As a note: if the constants should really be integers, then drop the single quotes. In fact, you can then simplify the query to:
UPDATE table
SET frontpage = (poll_id = 555)
WHERE user_id = 999;

Combining 2 Mysql update statments(same col, different values, different conditions)

I have been doing some searching but have not been able to find an answer for this so thought I would ask here as the people here know everything :)
I am trying to combine these 2 update queries into one query.
UPDATE addresses SET is_default='0' WHERE id!='1'
UPDATE addresses SET is_default='1' WHERE id='1'
I assume this should be too hard to accomplish but i cant seem to work it out :(
Thanks
Paul
You can use CASE to do this:
UPDATE addresses SET is_default = CASE WHEN id = 1 THEN 1 ELSE 0 END;
In your example, you're updating the entire table, so you wouldn't benefit from indexes no matter what, but if you were only doing a subset of values, you'd still want to leave the where in (because its very doubtful the optimizer could figure out how to use the index). For example:
UPDATE foo
SET
bar = CASE id WHEN 1 THEN 1 WHEN 2 THEN 0 ELSE bar END
baz = CASE WHEN id = 3 THEN 7 ELSE baz END
WHERE id IN (1,2,3)
(Note the two different CASE syntaxes).
UPDATE addresses SET is_default=IF(id='1', '1', '0')
Try this:
UPDATE addresses SET is_default= IF(id!='1', '0', '1')