NULL != NULL in mysql query - mysql

I am trying to do a query that sees if fields are equivalent. However, whenever the field is NULL it returns a false result. I even tried doing the same thing with the column itself:
SELECT * FROM `mturk_completion` WHERE (`mturk_completion`.`imdb_url` =
`mturk_completion`.`imdb_url` AND `mturk_completion`.`worker_id` = 'A3NF84Q37D7F35' )
And it only returns results where the column is not NULL. Why is this so, and how do I get around it?

Your title is absolutely correct for any SQL implementation (not just MySQL). NULL is not equal to anything (including another NULL).
You need to use explicit IS NULL check or COALESCE() function (or its RDBMS-dependent alternatives) to set some default value in case of NULL.

Your comparison of mturk_completion.imdb_url to itself is redundant and should always return True, except when mturk_completion.imdb_urlis Null, in which case it will return Null.
That's because the operator = returns either True, False when comparisons can be made or Null, when either of the two operators is Null
Try this to illustrate the situation.
SELECT 1 = NULL; -- returns NULL
SELECT 1 != NULL; -- also return NULL
SELECT ISNULL(1 = NULL); -- returns 1
SELECT ISNULL(1 != NULL); -- returns 1
If you rewrite your query like below, your problems with ignoring NULLs will go away:
SELECT * FROM `mturk_completion` WHERE worker_id = 'A3NF84Q37D7F35'

I think you can use
(table.Field = table2.Field OR COALESCE(table.Field, table2.Field) IS NULL)

Related

MySQL JSON_EXTRACT subquery not working when enclosed in IFNULL

Goal
Select a value based on a value returned by a subquery that is using JSON_EXTRACT which either returns a 'value' or NULL. IFNULL should be able to allow you to set a default value when the JSON_EXTRACT does not return a result.
Problem
When using a subquery that uses JSON_EXTRACT and returns a result, will return nothing when enclosed in IFNULL ignoring the default value.
Consider the following case
We want to select a SubscriptionPlan.name based on an identifier that is the result of a subquery using JSON_EXTRACT.
SELECT
subscriptionplan.name
FROM
SubscriptionPlan AS subscriptionplan
WHERE
subscriptionplan.identifier = (
SELECT
JSON_EXTRACT(product.data, '$.identifier')
FROM
Subscription AS subscription
JOIN
Product AS product ON product.productid = subscription.productid
WHERE
subscription.status = 'ACTIVE'
AND
subscription.ownerid = :userId
)
Case 1. SUCCESS without IFNULL
Subscription exists with status 'ACTIVE' and 'userId'
- Subquery result: 'PRO' and thus finds the SubscriptionPlan
- Final result: 'Professional'
Case 2. NOT FOUND without IFNULL
Subscription not found with status 'ACTIVE' and 'userId'
- Subquery result: NULL and thus does not find a SubscriptionPlan
- Final result: NULL
Now we add the IFNULL operation to default to 'FREE' subscription plan:
subscriptionplan.identifier = IFNULL(
( SELECT JSON_EXTRACT ... ),
'FREE'
)
Case 3. SUCCESS with IFNULL
Subscription exists with status 'ACTIVE' and 'userId'
- Subquery result: NULL even though the subscription was found !???
- Final result: NULL
Case 4. NOT FOUND with IFNULL
Subscription not found with status 'ACTIVE' and 'userId'
- Subquery result: FREE and thus finds the FREE SubscriptionPlan
- Final result: 'Free'
The IFNULL expression nullifies the subquery result, and it does not default to 'FREE'.
My thoughts are as follows:
Case 4: is using the IFNULL default value string 'FREE' and therefore works as intended
Case 3: subquery should return PRO and even if it returns NULL, it should default to 'FREE', neither happens
Maybe adding the IFNULL query adds another nesting layer where
What i've tried and did not work:
IF( () IS NULL, 'do stuff', 'do other stuff')
IF( ISNULL(<query<), 'do stuff', 'do other stuff')
IF( () = null , ..., ...)
IF( () = NULL , ..., ...)
IF( () = 'null' , ..., ...)
IF( () = 'NULL' , ..., ...)
Also according to Can't detect null value from JSON_EXTRACT:
IF ( JSON_EXTRACT(product.data, '$.identifier') = CAST('null' AS JSON), ...., ... )
All failures! Why is JSON_EXTRACT subquery not working when enclosed in IFNULL?
I've found out what caused the error.
JSON_EXTRACT adds quotes around its result resulting in "PRO" instead of PRO and therefore the IFNULL default is not triggered and the subscription plan, which is PRO, is not found using "PRO".
Add JSON_UNQUOTE around the JSON_EXTRACT solves the issue.

How to use null||d.AM_Answer for select query

I'm getting data from database and using union for joining 2 table. But I need to use null || d.AM_Answer. Here I'm using only null, null. But it's taking only null value coming. If I stored the answer, I'm not getting answer. So, I need to use null || d.AM_Answer.
select
b.QM_ID, b.QM_QCM_ID, b.QM_Question, b.QM_Type, b.QM_Parent_Id, null, null
from
question_master b
INNER JOIN Assessment_master d
on ( d. AM_QM_ID = b.QM_Parent_Id
AND d.AM_HNM_ID = %d
AND d.AM_HM_ID = %d
and d.AM_ASM_Local_Id = %# )
You can use ifnull to check if a field is null or not. If not null, then use field value.
Example:
IFNULL( d.AM_Answer, null )
This returns value of d.AM_Answer if it is not null.
And, you have some errors in your value comparison statements.
AND d.AM_HNM_ID = %d
AND d.AM_HM_ID = %d
AND d.AM_ASM_Local_Id = %#
If %d and %# are place holders for numerics, then it is wrong way of input.
For runtime value inputs, you have to use ? place holder and use prepared statements to bind values on those parameters.
AND d.AM_HNM_ID = ?
AND d.AM_HM_ID = ?
AND d.AM_ASM_Local_Id = ?
Use your server side scripting language for value binding.
Refer to:
MySQL: IFNULL(expr1,expr2)

Add where clause argument if variable is set

I have a WHERE-clause in my SQL-query, and would like to add an argument depending on if the #Fran variable is set.
If #Fran is NULL, then it shouldn't filter the results at all. Otherwise, if #Fran is set, then it should add a WHERE clause "AND franid=#Fran". How could i do that?
SELECT ...
FROM ...
WHERE ...
AND ((#Fran IS NULL) OR (#Fran IS NOT NULL AND franid=#Fran));
AND IFNULL(#Fran, franid) = franid
results in TRUE if #Fran is NULL (then it is essentially franid = franid) and in #Fran = franid if it is not NULL.

Null value matching in mySql

I have three tables in a mysql database . Deseasetype(DTID,TypeName) , Symptom(SID, SymptomName, DTID) , Result(RID, SID1, SID2, SID3, result).1st two table, i think is clear enough.
In result table: there will be combination's of symtoms and any values of SymID1/ SymID2/ SymID3 can be null. here i send a picture of the table result.
I want to input some symptom and output will be the result from the 'Result' table.
For that i wrote this query:
$query = "select Result from result where (result .SID1= '$symptom1') AND (result.SID2= '$symptom2' ) AND (result.SID3 = '$symptom3')";
This work only when three symptom's have value. but if any of the symptom's are null, then no result found. May be the query should be more perfect.
**please avoid any syntax error in my writing.
That's because you are comparing NULL to an empty string, and they aren't equal. You could try this instead:
SELECT Result
FROM symptom
WHERE IFNULL(symptom.SID1, '') = '$symptom1'
AND IFNULL(symptom.SID2, '') = '$symptom2'
AND IFNULL(symptom.SID3, '') = '$symptom3'
Notes:
You need to correctly escape the values of $symptom1, $symptom2 and $symptom3.
This won't efficiently use indexes.
As mark pointed out, the query is eventually falling down to compare with null if you are not escaping the null.
Or you can slightly change your logic to show a empty symptom with value '0' and then using the coalesce function you can easily build your query.
Does this work?
$query = "select Result from result
where (result.SID1 = '$symptom1' OR result.SID1 IS NULL) AND
(result.SID2 = '$symptom2' OR result.SID2 IS NULL) AND
(result.SID3 = '$symptom3' OR result.SID3 IS NULL)";

MySQL Left Join, SELECT a field either from one or the other if null

I am trying to LEFT JOIN 2 tables. which is working out fine. But i am getting back two sets of fields named setting_value. iam trying to get tblSettings.setting_value only if tblAgencySettings.setting_value is NULL. How would i go about doing this? I know i can rename the fields, then in PHP i can check the tblAgencySettings.setting_value and if NULL then grab the tblSettings.setting_value but i prefer to keep this at MySQL.
SELECT `tblSettings`.`id`, `tblSettings`.`setting_name`,
`tblSettings`.`setting_value`, `tblAgencySettings`.`setting_value`
FROM `tblSettings` LEFT JOIN `tblAgencySettings`
ON `tblSettings`.`id` = `tblAgencySettings`.`setting_id`
AND `tblAgencySettings`.`agency_id` = '1'
WHERE `tblSettings`.`changeable` = '1'
slight issue i just noticed. i failed to mention this. if tblAgencySettings.setting_value does have a value. but changeable is not 1 then just select tblSettings.setting_value
Just add a COALESCE:
SELECT `tblSettings`.`id`, `tblSettings`.`setting_name`,
COALESCE(`tblAgencySettings`.`setting_value`, `tblSettings`.`setting_value`)
FROM `tblSettings` LEFT JOIN `tblAgencySettings`
ON `tblSettings`.`id` = `tblAgencySettings`.`setting_id`
AND `tblAgencySettings`.`agency_id` = '1'
WHERE `tblSettings`.`changeable` = '1'
The COALESCE function returns the first non-NULL value you give it so this:
COALESCE(`tblAgencySettings`.`setting_value`, `tblSettings`.`setting_value`)
Will be tblAgencySettings.setting_value if that's not NULL and tblSettings.setting_value if tblAgencySettings.setting_value is NULL.
If tblAgencySettings.setting_value can also be zero and you want to ignore that as well as NULL, then you could use this instead of the COALESCE above:
COALESCE(
IF(`tblAgencySettings`.`setting_value` = 0, NULL, `tblAgencySettings`.`setting_value`),
`tblSettings`.`setting_value`
)
The IF returns the second argument if the first is true and the third if the first argument is false so the above use converts zero to NULL. Or, you could go all the way to a CASE statement:
case
when `tblAgencySettings`.`setting_value` = 0 then `tblSettings`.`setting_value`
when `tblAgencySettings`.`setting_value` IS NULL then `tblSettings`.`setting_value`
else `tblSettings`.`setting_value`
end
Change your SQL Statement to this:
SELECT `tblSettings`.`id`, `tblSettings`.`setting_name`,
CASE WHEN `tblSettings`.`setting_value` IS NULL THEN `tblAgencySettings`.`setting_value`
ELSE `tblSettings`.`setting_value` END AS `setting_value`
FROM `tblSettings` LEFT JOIN `tblAgencySettings`
ON `tblSettings`.`id` = `tblAgencySettings`.`setting_id`
AND `tblAgencySettings`.`agency_id` = '1'
WHERE `tblSettings`.`changeable` = '1'
Here's a link to MYSQL CASE Statement for your reference.