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

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.

Related

How to dynamically pass column name while framing the case statement in MySQL

I'm writing a query in MySQL wherein, i'm framing a case statement to get some values. However, i'm not getting any way to pass the column name dynamically in the 'then' statement of the case clause. Below is the code am trying.
SELECT CONCAT (COLUMN_NAME,(CASE WHEN
IS_NULL_FLAG = 'Y' AND COLUMN_TYPE = 'NUMBER' then '== ? (int ?) null:Convert.ToInt32(#COLUMN_NAME) AS #COLUMN_NAME'
else ''
end
) )FROM SCHEMA_REF WHERE SCHEMA_REF.ENTITY_NAME = 'CUSTOMERS1_REP' ORDER BY SCHEMA_ID;
Here while fetching the record, i'm trying to get the column name, but it is not getting passed.
Any idea on how can I pass the column name dynamically in the 'then' clause of the case statement.
Thanks,
Arjun

update a table based on the outcome of a join in MySQL

I understand the syntax here:
UPDATE table
SET column1 = expression1,
column2 = expression2,
...
WHERE conditions;
and here:
UPDATE table1
SET column1 = (SELECT expression1
FROM table2
WHERE conditions)
WHERE conditions;
...but what if I want to update
UPDATE table1
SET column1 = expression
if we get a particular result on a join between table1 and table2
which has WHERE conditions?
I can't seem to figure it out, and I get syntax errors in all of my attempts. Any advice greatly appreciated.
The syntax in MySQL is:
UPDATE table1 JOIN
table2
ON conditions
SET table1.column1 = table2.expression1
WHERE conditions;
What I do is write it as a SELECT statement first.
SELECT t.id
, t.col AS old_val
, s.expr AS new_val
FROM target_table t
JOIN source_table s
ON s.somecol = t.somecol
AND s.othercol < 1
WHERE s.something_else = 'abc'
In this example, t.col is the column that I (eventually) want to assign a new value to. (Used in the SELECT statement here, this just displays the value currently stored in the column.)
The expression s.expr represents the expression that returns the value I want to assign to col. This could be as simple as a column reference, or can be a more complex expression.
The rest of the statement are the normal FROM, JOIN, ON and WHERE clauses we're familiar with.
Once I have a SELECT statement that is working, I can convert that into an UPDATE statement by
replacing SELECT ... FROM (at the beginning of the statement) with the keyword UPDATE
adding a SET clause before the WHERE clause.
For example, I would convert the SELECT statement above to something like this, to assign the value of s.expr to t.col:
UPDATE target_table t
JOIN source_table s
ON s.somecol = t.somecol
AND s.othercol < 1
SET t.col = s.expr
WHERE s.something_else = 'abc'
This the approach that works for me. Writing it as a SELECT first allows me to test, muck with the conditions and expressions, and review to verify which rows are going to be updated, what values are being replaced, and what values are going to be assigned to each row.

Mysql Update 2 columns from 2 different tables with extra condition

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.)

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

How to count all NULL values in a table?

Just wondering, is there any quick way to count all the NULL values (from all columns) in a MySQL table?
Thanks for any idea!
If you want this done exclusively by MYSQL and without enumerating all of the columns take a look at this solution.
In this method you don't have to maintain the number of database columns by hard coding them. If your table schema will get modified this method will work, and won't require code change.
SET #db = 'testing'; -- database
SET #tb = 'fuzzysearch'; -- table
SET #x = ''; -- will hold the column names with ASCII method applied to retrieve the number of the first char
SET #numcolumns = 0; -- will hold the number of columns in the table
-- figure out how many columns we have
SELECT count(*) into #numcolumns FROM information_schema.columns where table_name=#tb and table_schema=#db;
-- we have to prepare some query from all columns of the table
SELECT group_concat(CONCAT('ASCII(',column_name,')') SEPARATOR ",") into #x from information_schema.columns where table_name=#tb and table_schema=#db;
-- after this query we have a variable separated with comma like
-- ASCII(col1),ASCII(col2),ASCII(col3)
-- we now generate a query to concat the columns using comma as separator (null values are omitted from concat)
-- then figgure out how many times the comma is in that substring (this is done by using length(value)-length(replace(value,',',''))
-- the number returned is how many non null columns we have in that column
-- then we deduct the number from the known number of columns, calculated previously
-- the +1 is added because there is no comma for single value
SET #s = CONCAT('SELECT #numcolumns - (length(CONCAT_WS(\',\',', #x, '))-length(replace(CONCAT_WS(\',\',', #x, '),\',\',\'\')) + 1) FROM ',#db,'.',#tb,';');
PREPARE stmt FROM #s;
EXECUTE stmt;
-- after this execution we have returned for each row the number of null columns
-- I will leave to you to add a sum() group call if you want to find the null values for the whole table
DEALLOCATE PREPARE stmt;
The ASCII is used to avoid reading, concatenating very long columns for nothing, also ASCII makes us safe for values where the first char is a comma(,).
Since you are working with reports, you may find this helpful as this can be reused for each table if you put in a method.
I tried to let as many comments as possible.
Let's split on pieces the above compact way (reverse way):
I wanted to end up having a query like this
SELECT totalcolumns - notnullcolumns from table; -- to return null columns for each row
While the first one is easy to calcule by running:
SELECT count(*) FROM information_schema.columns where table_name=#tb and table_schema=#db;
The second one the notnullcolumns is a bit of pain.
After a piece of examination of the functions available in MySQL, we detect that CONCAT_WS does not CONCAT null values
So running a query like this:
SELECT CONCAT_WS(",","First name",NULL,"Last Name");
returns: 'First name,Last Name'
This is good, we take rid of the null values from the enumeration.
But how do we get how many columns were actually concatenated?
Well that is tricky. We have to calculate the number of commas+1 to get the actually concatenated columns.
For this trick we used the following SQL notation
select length(value)-length(replace(value,',','')) +1 from table
Ok, so we have now the number of concatenated columns.
But the harder part is coming next.
We have to enumerate for CONCAT_WS() all values.
We need to have something like this:
SELECT CONCAT_WS(",",col1,col2,col3,col4,col5);
This is where we have to take use of the prepared statements, as we have to prepare an SQL query dynamically from yet unknown columns. We don't know how many columns will be in our table.
So for this we use data from information_schema columns table. We need to pass the table name, but also the database name, as we might have the same table name in separate databases.
We need a query that returns col1,col2,col3,col4,col5 to us on the CONCAT_WS "string"
So for this we run a query
SELECT group_concat(column_name SEPARATOR ",") into #x from information_schema.columns where table_name=#tb and table_schema=#db;
One more thing to mention. When we used the length() and replace() method to find out how many columns were concatenated, we have to make sure we do not have commas among the values. But also take note that we can have really long values in our database cells. For both of this trick we use method ASCII('value'), which will return the ASCII char of the first char, which cannot be comma and will return null for null columns.
That being said we can compact all this in the above comprehensive solution.
Something like
select id
, sum ( case when col1 is null then 1 else 0 end case ) col1
, sum ( case when col2 is null then 1 else 0 end case ) col2
, sum ( case when col3 is null then 1 else 0 end case ) col3
from contacts
group by id
Something like this (substitute COL_COUNT as appropriate):
select count(*) * COL_COUNT - count(col1) - count(col2) - ... - count(col_n) from table;
You should really do this using not only SQL, but the language which is at your disposal:
Obtain the metadata of each table - either using DESCRIBE table, or using a built-in metadata functionality in your db access technology
Create queries of the following type in a loop for each column. (in pseudo-code)
int nulls = 0;
for (String colmnName : columNames) {
query = "SELECT COUNT(*) FROM tableName WHERE " + columnName + " IS NULL";
Result result = executeQuery(query);
nulls += result.size();
}