mySQL Conditional Syntax Issue - mysql

Essentially I would like to determine a value based on a conditional and then use that value inside a different conditional all in the same select statement.
Example:
IF(IF (`date1` IS NOT NULL AND `date1 ` <> 0),
`date1`, `date2` AS processdate) = curdate(), "ready", "not ready" AS action_status
To determine processdate I am saying check the field date1 has a date, if so use it, otherwise use date2 as processdate.
Once processdate is determined, compare it to todays date, if they are equal set action_status = "ready", otherwise "not ready".
I believe the syntax is incorrect, what is the correct format for something like this?

AS can only apply to an entire expression for a return value of the select; you can't embed it in an expression. And each IF needs parentheses around its three arguments. So:
IF(
curdate() =
IF(
`date1` IS NOT NULL AND `date1 ` <> 0,
`date1`,
`date2`
),
"ready",
"not ready"
) AS action_status
(I changed ... = curdate() to be curdate() = ... just because I think it's more readable that way; either would work.)

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 convert calculated formula from salesforce to SQL

We have one Opportunity table in salesforce and this table has one calculated column called as "Is_XYZ".
Calculated formula for "Is_XYZ" column is -
calculatedFormula: IF(
AND(
OR(
AND(
UPPER(LeadSource__c) == 'XYZ',
DateValue(CreatedDate) > Date(2017,01,01)
),
AND( Is_PQR ,
IF(
Effective_Date__c <> null,
DateValue(CreatedDate) > Effective_Date__c ,
TRUE
),
IF(
Effective_Date__c <> null,
Effective_Date__c <= TODAY(),
TRUE
)
)
),
UPPER(MailingState) <> 'NY',
UPPER(Lead_Sub_Source__c) <> 'PQRS'
),
TRUE,
FALSE
)
We have created same Opportunity table in Hive SQL and we want to write select query to calculate "Is_XYZ" column value. We have converted formula from salesforce syntax to SQL syntax.
So, formula in SQL will be -
SELECT
IF(
(
(
( UPPER(LeadSource__c) == 'XYZ' AND
CreatedDate > '2017-01-01'
)
OR
( Is_PQR AND
IF( Effective_Date__c IS NOT NULL,
CreatedDate > Effective_Date__c,
TRUE
)
AND
IF( Effective_Date__c IS NOT NULL,
Effective_Date__c <= current_date,
TRUE
)
)
)
AND (UPPER(MailingState) <> 'NY')
AND (UPPER(Lead_Sub_Source__c) <> 'PQRS')
),
TRUE,
FALSE
) as Is_XYZ
FROM Opportunity;
Can you help me to confirm that both formulas(salesforce and SQL) are same? I mean, can you verify that both above formulas are doing same thing.
I tested it on both sides(salesforce and Hive SQL) and it is behaving differently. Values for that case are -
LeadSource__c = abcdef
Lead_Sub_Source__c = klmnop
CreatedDate = 2019-04-02T00:06:49.000Z
MailingState = HI
Is_PQR = true
Effective_Date__c = 2019-04-09
For above values, salesforce displays Is_XYZ = true and hive displays Is_XYZ = false. Please help me in identifying the issue.
I can tell that the date/time arithmetic is not correct, due to time components on the values. I don't know if this is the issue with your particular bad example.
For instance:
DateValue(CreatedDate) > Date(2017,01,01)
is not equivalent to:
CreatedDate > '2017-01-01'
The equivalence would be to:
CreatedDate >= '2017-01-02'
The issue is the DateValue() which removes the time component.
Similarly,
DateValue(CreatedDate) > Effective_Date__c ,
requires a modification.
Finally, we found that there is bug in Salesforce formula.
In Salesforce formula, we are checking "Effective_Date__c <> null" which is always returning false. In Salesforce, it is preferred to use IsBlank() function than IsNull().
So, we have changed CalculatedFormula in Salesforce to correct this issue. New formula will be - IsBlank(Effective_Date__c).
I am not a Salesforce developer, so not able to pick this bug earlier. After discussing this with Salesforce developer, we are able to find this bug which is present in system from last one year.
I found no way in Salesforce workbench to test/debug this Calculated field formula which is very frustrating.

Combining multiple condition in single case statement

Does Invantive SQL support multiple condition in a single case statement? I the statement below, I did not get any results. Tried the same statement with only 1 condition (no cascade), this retrieved the expected result.
select prj.code
, prj.startdate
, prj.enddate
from exactonlinerest..projects prj
where prj.code between $P{P_PROJECT_FROM} and $P{P_PROJECT_TO}
and case
/* when (prj.enddate is null or prj.enddate >= sysdate)
then 'Y'
when (prj.enddate is not null and prj.enddate <= sysdate)
then 'N' */
when prj.startdate <= sysdate
then 'B'
end
= $P{P_PROJECT_ACTIVE_FROM}
I think you where clause is not correctly formulated. With Exact Online, a project either has:
option 1: no end date,
option 2: an end date in the past
option 3: or an end date in the future
The first part of the case handles option 1 and option 3. The second part handles option 2. So there is never an outcome of 'B' in the case.
To analyze such problems, I recommend include the case in the select clause and removing the filter. That gives you a view of the possible outcomes.
Example:
use 868056,102673
select prj.division
, prj.code
, prj.startdate
, prj.enddate
, case
when prj.enddate is null or prj.enddate >= sysdate
then 'Y'
when prj.enddate is not null and prj.enddate <= sysdate
then 'N'
when prj.startdate <= sysdate
then 'B'
end
indicator
from exactonlinerest..projects prj
where prj.code between $P{P_PROJECT_FROM} and $P{P_PROJECT_TO}

If Statement in MySQL Select

According to the docs a if works as follows:
IF(expr1,expr2,expr3)
If expr1 is TRUE (expr1 <> 0 and expr1 <> NULL) then IF() returns expr2; otherwise it returns expr3 [...].
Here is a random fiddle that represents my problem: http://sqlfiddle.com/#!9/8076e2/1
Basically what I'm trying to do is the following:
SELECT IF(whatever, 1, 2) FROM testing WHERE whatever = 'abc';
Since there is a record there that matches my WHERE clause it basically means that whatever won't be 0 or NULL like specified in the docs. Then why am I getting expression3 as result?
expr1 is intended to be a boolean expression, or at least a numeric value, not a string.
You can use true and false, or 1 and 0, etc. Technically any non-zero numeric value is interpreted as true.
Since you are using the string 'abc' as expr1, MySQL is implicitly converting that to the number 0, which represents false.
In order to return one result for a non-empty string, and another result for empty string or null, you can use a query like this:
SELECT if((whatever is not null and whatever != ''), 1, 2)
FROM testing
WHERE whatever = 'abc';
You can also do the same thing with CASE if you want to follow the SQL standard:
SELECT (case when (whatever is not null and whatever != '') then 1 else 2 end)
FROM testing
WHERE whatever = 'abc';
SELECT IF(COUNT(whatever) > 0, 1, 2) FROM testing WHERE whatever = 'abc';

Calculate Percent Difference in SQL Server

I have two months with two values, for example:
July-2013 1838.08
Aug-2013 3500.08
How can I calculate the percentage difference in August compared with July?
The formula for this is easy it's (Curr-Prev)*100.0/Prev, what's not clear is how to apply it since we do not know your table definition, contents or keys, and thus do not know how to generically select one month and it's previous value. But, hard-coding it would be like this:
SELECT
100.0*(curr.Val - prev.Val) / prev.Val As PercentDiff
FROM yourTable As curr
JOIN yourTable As prev
ON curr.MonthStr = 'Aug-2013' AND prev.MonthStr = 'July-2013'
The problem with working out percentage changes is that you need to be careful of when the 'old value' is 0 or you will get an error.
One approach is using nullif(old_Value, 0) but then the problem with that is when old values are 0 you are asking for New_Value/NULL which is the new value. (definitely not the % change)
I worked around it like this:
(case
when
OldValue = 0 and NewValue = 0
then
cast(0 as Decimal(10,2))
when
OldValue = 0
then
'Na'
else
cast(cast(
(
(
(cast(NewValue as decimal(11,3)) -
cast(OldValue as decimal(11,3))
)*100
)/cast(OldValue as decimal(11,3))
) as decimal(20,3)
) as varchar
)
end) '% Change'
I probably threw a lot more casts than necessary but it works well for me. Gives Na when necessary and 0 when necessary.
SELECT VAR(Bonus) 'Variance',
STDEVP(Bonus) 'Standard Deviation',
STDEV(Bonus) 'Standard Deviation',
VARP(Bonus) 'Variance for the Population'
FROM Sales.SalesPerson;
giving credit to fololwing post
http://blog.sqlauthority.com/2008/01/20/sql-server-introduction-to-statistical-functions-var-stdevp-stdev-varp/
to handle zeroes in the denominator, i use:
case
when oldVal<>0 then ((newVal-oldVal)*100.0)/oldVal
else
case when newVal=0 then 0 else Null end
end
this will return 0 if newVal and oldVal are both 0, and Null if oldVal is zero but newVal is non-zero.
multiplying by 100.0 (as opposed to 100) will implicitly convert int fields into decimal. i find it cleaner than try_convert().