0

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?

1
  • You need to use json_value or ->> as you already figured out the problem. Commented Mar 4, 2022 at 13:28

1 Answer 1

1

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.

Sign up to request clarification or add additional context in comments.

3 Comments

product.data->>'$.identifier' is more simple than JSON_UNQUOTE(JSON_EXTRACT(product.data, '$.identifier'))
Select a value based on a value returned by a subquery that is using JSON_EXTRACT which either returns a 'value' or NULL. It seems that you confuse SQL NULL and JSON null which are NOT the same.
also because a JSON null value is not a SQL NULL, you probably want to wrap the ->> call in a NULLIF - ie. IFNULL(NULLIF(product.data->>'$.identifier','null'),'FREE')

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.