Mysql Update 2 columns from 2 different tables with extra condition - mysql

I want to update two different columns from two different tables in mysql. This is the brief version of what I want to do.
In more detail I want to update a column from table 1 only if a condition is true. Otherwise I want to update a other column from table 1.
The same I want to do for table 2 and this should be all done in a single UPDATE statement.
I tried something like this:
UPDATE `grouped_messages`
JOIN `messages` ON (`messages`.group_msg_id = 1) SET
(CASE WHEN(`grouped_messages`.`conversation_partner1`=10) THEN `grouped_messages`.`deletion_status_partner1`=1
WHEN(`grouped_messages`.`conversation_partner2`=10) THEN `grouped_messages`.`deletion_status_partner2`=1 END),
(CASE WHEN(`messages`.`from`=10) THEN `messages`.`deletion_status_from`=1
WHEN(`messages`.`to`=10) THEN `messages`.`deletion_status_to`=1 END);
but this is not working. Does anybody know a solution, which would work for my case?

You can't do an assignment within a CASE expression. Your SET clause is invalid. It needs to be SET column = expression.
To have the column conditionally updated; that is, to have the column not updated, have the expression return the current value of the column.
Let's use an alias of g for grouped_messages.
When the condition you are checking is true, you want the SET clause to be equivalent to:
SET g.deletion_status_partner1 = 1
When the condition is not true, you want to assign the current value of the column to itself, so the SET clause to equivalent to:
SET g.deletion_status_partner1 = g.deletion_status_partner1
To get that, you could do something like this:
SET g.deletion_status_partner1
= CASE WHEN g.conversation_partner1 = 10
THEN 1
ELSE g.deletion_status_partner1 -- existing column value
END
To modify an additional column, you'd need to add to the SET clause
, g.deletion_status_partner2
= CASE WHEN some_other_condition
THEN new_value
ELSE g.deletion_status_partner2 -- existing column value
END
(I haven't checked anything else in your statement; I only highlight the most obvious issue, and how to get an update statement to do "conditional" assignment.)

Related

Why AND after a SET is not a syntax error in mysql?

I was surprised that this is not a syntax error:
UPDATE mytable
SET deleted = 1
AND name = 'Cindy'
It doesn't affect the result of the command, is there any use of adding an AND after a SET? Or mysqsl will just ignore it?
Because the expression:
1 AND name = 'Cindy'
is a Boolean expression that evaluates to 0 for False or 1 for True
and the value of this expression will be assigned to the column deleted, like:
SET deleted = (1 AND (name = 'Cindy'))
The statement takes into account the operators precedence. And the query acts as
UPDATE mytable
SET deleted = (1 AND (name = 'Cindy'))
I.e. firstly the condition name = 'Cindy' is tested producing TRUE (1), FALSE (0) or NULL.
Then the expression 1 AND {result} is evaluated.
And finally the result of this expression evaluation is assigned into deleted column.
DEMO fiddle
If you receive the same result like for
UPDATE mytable
SET deleted = 1
then name column value is equal to 'Cindy' using current collation.

Subquery returns more than 1 row. Using SQL select to update a different tables results

I am trying to update a column in the following table 'jobqueue' using the results from a SELECT query performed on the 'mdtinfo' table.
The column I am trying to update is called ignore and I need to set the value to 1 from its default of 0.
update jobqueue
set jobqueue.`ignore`= '1'
where (SELECT JobQueue_job_queue_id
FROM mdtinfo
WHERE product_name = 'Example')
The above query returns the following error: SQL Error (1242): Subquery returns more than 1 row.
When running the select query on it's own it returns results successfully.
In MySQL, a value of zero appearing in a WHERE clause means false.
So, UPDATE something SET col=val WHERE (SELECT colx FROM sometable) has the potential to be a valid query. If the inner SELECT gets just one row, and its colx column has the value 0, the update won't do anything. If the colx column has a nonzero value the query means UPDATE something SET col=val WHERE true. Accordingly, every row in sometable will be updated. I doubt that's what you want.
If the inner SELECT happens to return more than one row, the query isn't valid. You'll get the error 1242 you actually received.
(This business of interpreting numbers as Boolean values causes MySQL to accept some otherwise dodgy query syntax, like the syntax in your question.)
I guess you want to retrieve the job_queue_id values for the row or rows you actually want to update. So try something like this.
update jobqueue
set jobqueue.`ignore`= '1'
where jobqueue.job_queue_id IN (SELECT JobQueue_job_queue_id
FROM mdtinfo
WHERE product_name = 'Example')
I guessed you have a column jobqueue.job_queue_id. You didn't tell us what columns you have in jobqueue.
update jobqueue
set jobqueue.`ignore`= '1'
where jobqueue.`job_queue_id` IN (SELECT GROUP_CONCAT(JobQueue_job_queue_id)
FROM mdtinfo
WHERE product_name = 'Example' GROUP BY product_name)
you should write column name in where condition.

MySQL INSERT INTO Mytable VALUES(NULL) WHERE VALUES ('NA');

I have in Mytable some value = 'NA'
Insted of this value I would like to put NULL.
So I've write:
INSERT INTO Mytable
VALUES(NULL)
WHERE VALUES('NA');
But I didn't work.
I didn't put the name of the column because potentially all column can have some 'NA' value.
I hope someone have a idea to do it.
Regards
Sam
UPDATE Mytable
SET value = NULL
WHERE value = 'NA';
Yes, you must do this for each column/attribute that you want to update.
UPDATE Mytable SET value = NULL WHERE value = 'NA'
To replace occurrences of 'NA' with NULL in multiple columns, for all rows in a table, you can do this in a single update query. The trick is to assign the current value of the column back to the column when you don't want the value changed.
For example:
UPDATE Mytable t
SET t.column_one = IF(t.column_one='NA',NULL,t.column_one)
, t.column_two = IF(t.column_two='NA',NULL,t.column_two)
, t.column_fee = IF(t.column_fee='NA',NULL,t.column_fee)
WHERE t.column_one = 'NA'
OR t.column_two = 'NA'
OR t.column_fee = 'NA'
NOTES:
Repeat the column assignment for each column you need to do the replacement. (The example above references three columns, named column_one, column_two and column_fee. I don't know the names of the columns in your table; you would need to replace those references with the actual names of the columns in your table.)
The WHERE clause is optional; the query would have the same net result without that WHERE clause. (Without the WHERE clause, the query would update every row in the table; any rows that don't have an 'NA' in one of the three columns would not be changed, since the columns will all be assigned their current values.
For a lot of columns, it's more efficient to do it in a single operation, to apply several changes to a row in one statement, rather than separate statements each making updates to the same row.)
The expresssion IF(a,b,c) evaluates expression a as a boolean; if it returns TRUE, it returns expression b, otherwise it returns expression c.
To see how this works, you can run a SELECT statement (remove the SET clause, and replace the UPDATE keyword with SELECT and relevant expressions in the SELECT list:
For example:
SELECT t.column_one AS _one_old
, IF(t.column_one='NA',NULL,t.column_one) AS _one_new
, t.column_two AS _two_old
, IF(t.column_two='NA',NULL,t.column_two) AS _two_new
, t.column_fee AS _fee_old
, IF(t.column_fee='NA',NULL,t.column_fee) AS _fee_new
FROM Mytable t
WHERE t.column_one = 'NA'
OR t.column_two = 'NA'
OR t.column_fee = 'NA'
The _old columns return the existing values in the columns; the _new columns return the value that would be assigned (by the UPDATE statement earlier in my answer.)
The results from that query will verify that IF() expressions will return a NULL when the existing value in the column is 'NA'; it will also confirm that the IF() expression will return the existing value when the existing value in the column is not 'NA'.
FOLLOWUP
With 20 different tables with 12 columns each, I'd make use of the information_schema.columns table in MySQL to help me generate the required expressions.
Something like this:
SELECT CONCAT(' , t.'
,c.column_name,' = IF(t.'
,c.column_name,'=''NA'',NULL,t.'
,c.column_name,')') AS expr
FROM information_schema.columns c
WHERE c.table_schema = 'mydatabase' -- the name of your database
AND c.table_name = 'mytable' -- the name of your table
AND c.data_type IN ('varchar','char') -- only character type columns
ORDER BY c.ordinal_position
Which will return something like this:
expr
-------------------------------------
, t.fee = IF(t.fee='NA',NULL,t.fee)
, t.fi = IF(t.fi='NA',NULL,t.fi)
, t.fo = IF(t.fo='NA',NULL,t.fo)
, t.fum = IF(t.fum='NA',NULL,t.fum)
So, this doesn't actually update the table, it's just a convenient way to avoid typing out a bunch of SQL expressions. You can copy that result set, and use it to form a statement similar to the one I showed in my answer above. (Obviously, you would omit rows that you don't want to change, and the first comma would need to be changed to the SET keyword, and the rest of the statement would need to be wrapped around this.
Personally, I wouldn't bother with a WHERE clause, because if it's a lot of columns, the query is going to do a full scan of the table anyway.
SELECT CONCAT(' OR t.',c.column_name,' = ''NA''') AS expr
FROM information_schema.columns c
WHERE c.table_schema = 'mydatabase' -- the name of your database
AND c.table_name = 'mytable' -- the name of your table
AND c.data_type IN ('varchar','char') -- only character type columns
ORDER BY c.ordinal_position
This will return something like:
expr
----------------------
OR t.fee = 'NA'
OR t.fi = 'NA'
OR t.fo = 'NA'
OR t.fum = 'NA'
CAUTION: be careful that you don't do comparison of numeric columns to 'NA', because MySQL will evaluate 'NA' as a numeric value of zero (0) in a numeric context.

SQL Query about checking a column value if it equals a given value then do something

i have a table named FullSchedule and it contains teachers names and days and times within each day, and i want to write a Query as the following question
select all fields from FullSchedule, if the teacher's name = 'SomeName' then add a column called Check with the value 'Found' else if not found put the value 'Not Found'
what is the correct Query for this question ? notice that the teacher's column contains different names but i want to check for one of them. simply making a schedule for each teacher.
I would have that column in my table with a predefined value, let's say it's 'Not found' or 'Not checked' and then I would set that variable with a query of the type:
UPDATE table_name
SET column1 = value1, column2 = value2...., columnN = valueN
WHERE [condition];
If that doesn't fit your needs, you can try a set query from a query or something like this

mysql get column name when column value matches constraint

I'm trying to get column names from a table. I want to supply the row id and I want only the column names for which the value of that column for the specific row (identified by the id) is "true" (my table has a bunch of boolean fields).
I want something like:
SELECT COLUMN_NAME
FROM INFORMATION_SCHEMA.COLUMNS
WHERE COLUMN_NAME.value = true
AND TABLE_THE_COLUMN_IS_FROM.id = "some_id"
Where .value would be variable, basically checking each column to see if it were true.
I know I can just get the row's values and iterate through, returning only those with value true, but I wanted to see if there is a way to do it all in one step. Thanks in advance to anyone who knows!
There is no means in one query to dynamically scan through the table's schema and inspect its values. The best way to achieve what you want is the one you suggested: query for the row client-side and then cycle through the columns searching for the values you seek. The other alternative is to query for the table schema using the INFORMATION SCHEMA views client-side, build a SQL statement with a where clause that looks for a True value in all the boolean columns, execute that and inspect the results.
This is probably going to be rather ugly no matter how you cut it, but here's one option:
select columns.column_name
from bool_table
inner join information_schema.columns
on columns.table_schema = 'your_db'
and columns.table_name = 'bool_table'
and ((columns.column_name = 'bool_1' and bool_table.bool_1 = 1)
or (columns.column_name = 'bool_2' and bool_table.bool_2 = 1))
where bool_table.id = 25
You could also potentially query information_schema.columns to dynamically generate the list of column statements so that you could dynamically generate the query, and even execute it in a stored proc using dynamic sql in mysql.