MySQL compare different values in case when function - mysql

In this query I use the CASE WHEN function to compare variables values in two different conditions. The problem is the number, because return a value = 1, but the correct result is NULL (20 is > of 8).
SELECT DISTINCT
case
when '20'>= '8' then null
when '20'< '8' then '1'
ELSE '0'
end checkValue
FROM DUAL;
How to resolve this problem?
The query run correctly if change 8 with 08. This solution is not applicable to because from variable arrive numers: 10 100 1000 units.
Thanks

I have change the field type from VARCHAR to DECIMAL and in this case work fine.

if you want compare string remember that string '20' < '8' so 'AB' is < 'C'
SELECT DISTINCT
case
when '20'>= '08' then null
when '20'< '08' then '1'
ELSE '0'
end checkValue
FROM DUAL;
otherwise if you want a number compare then you shoudl convert tne string as number

You need just cast strings to some numeric data type and then compare, for example
SELECT DISTINCT
case
when cast('20' as signed)>= cast('8' as signed) then null
when cast('20' as signed)< cast('8' as signed) then '1'
ELSE '0'
end checkValue
FROM DUAL;
Side note: DISTINCT no makes sense in this particular case

Related

MySQL query to return 1 and 0 based on difference between dates

In MySQL Database I have a table ABC that consists of a column 'LastDate'.
LastDate which has datatype as DATETIME. The default value for this 'NULL'
I need to write a query for the table which would
Return '1' in these cases.
1) If DATEDIFF(CURRENT_TIME,LastDate) is >15 or if DATEDIFF(CURRENT_TIME,LastDate) is
NULL(i.e defaultVal).
return '0' if DATEDIFF(CURRENT_TIME,LastDate) is <15.
I tried to write an SQL query for this but was unable to do it. Please help me write this Query. Thanks in advance.
You can be explicit about your logic:
select t.*,
(case when DATEDIFF(CURRENT_TIME, LastDate) > 15 or
LastDate is null
then 1 else 0
end) as flag
from t;
This can be simplified to:
select t.*,
coalesce(DATEDIFF(CURRENT_TIME, LastDate) <= 15, 1) as flag
from t;

How to group same kind of values into common one and group by that

Hi I was looking for a mysql query result like
As you can see there are some values have the kind of values (Ex: BV and BR or C5 and C7) how can I combine then together into one common value lets say B or C and group by that in sql?
I have the following query:
SELECT
type,
sum(case when status ='valid' then 1 else 0 end) valid_jobs,
sum(case when status ='non-valid' then 1 else 0 end) non_valid_jobs,
sum(case when status IS NULL then 1 else 0 end) null_jobs
from
main_table
where
SUBSTRING_INDEX(CAST(CAST(from_unixtime(date_generated) AS DATE) AS CHAR), '-',2) REGEXP '^2016'
group by type
Thanks in advance guys.
Otcome will look like:
Just use an expression that evaluates the value of the type column, and returns the desired result.
What's not clear from the question is the "mapping" from type to the value you want returned in the first column. It looks like we might be looking at just the first character of value in the type column.
SUBSTR(type,1,1)
If the "mapping" is more involved, then we could use a CASE expression. For example:
CASE
WHEN type IN ('BV','BR','BT','ZB') THEN 'B'
WHEN type IN ('C5','C7') THEN 'C'
WHEN ... THEN ...
ELSE type
END
We'd use that as the first expression in the SELECT list (replacing the reference to the type column in the original query), and in the GROUP BY clause.
On an (unrelated) performance note, we'd prefer conditions in the WHERE clause to be on bare columns. That allows MySQL to make use of an (efficient) range scan operation on an appropriate index.
With this condition:
WHERE SUBSTRING_INDEX(CAST(CAST(FROM_UNIXTIME( t.date_generated ) AS DATE) AS CHAR), '-',2)
REGEXP '^2016'
We're forcing MySQL to evaluate the expression on the left side for every row in the table. And the value returned by the expression is compared.
If what we're really trying to do is get date_generated values in 2016, assuming that date_generated is INTEGER type, storing 32-bit unix-style number of seconds since beginning of the era 1970-01-01...
We can do something like this:
WHERE t.date_generated >= UNIX_TIMESTAMP('2016-01-01')
AND t.date_generated < UNIX_TIMESTAMP('2017-01-01')
MySQL will see that as a range operation on the values in te date_generated column. And with that, MySQL can make effective use of an index that has date_generated as a leading column.
Just replace expr with the expression that returns the values you want in the first column:
SELECT expr
, SUM(IF( t.status = 'valid' ,1,0)) AS valid_jobs
, SUM(IF( t.status = 'non-valid' ,1,0)) AS non_valid_jobs
, SUM(IF( t.status IS NULL ,1,0)) AS null_jobs
FROM main_table t
WHERE t.date_generated >= UNIX_TIMESTAMP('2016-01-01')
AND t.date_generated < UNIX_TIMESTAMP('2017-01-01')
GROUP BY expr
EDIT
To guarantee that rows are returned in a particular sequence, add an ORDER BY clause, e.g.
ORDER BY 1
try this,
SELECT
LEFT(type,1) AS type,
sum(case when status ='valid' then 1 else 0 end) valid_jobs,
sum(case when status ='non-valid' then 1 else 0 end) non_valid_jobs,
sum(case when status IS NULL then 1 else 0 end) null_jobs
FROM
main_table
WHERE
SUBSTRING_INDEX(CAST(CAST(from_unixtime(date_generated) AS DATE) AS CHAR), '-',2) REGEXP '^2016'
GROUP BY
type

DATEDIFF SQL Query

I am at the final stage of my project and have the problem to find if a job is overdue. I link this to priority for example if a job has a priority of 1 it must be complete in 1 day, a priority of 4 then 4 days.
I have come up with a CASE however this doesn't seem to work any help would be appreciated.
SELECT `defect_Id`,`Overtasked`
WHERE
CASE DATEDIFF(DD,`date_Investigaton` - `CURRENT_DATE()`) >= `priority` AS Overtasked
THEN `Overtasked` == 'YES'
ELSE `Overtasked` == 'NO'
END
Solution
`SELECT defect_Id,
CASE WHEN DATEDIFF(date_Investigated, CURDATE()) >= priority
THEN 'YES'
ELSE 'NO'
END AS Overtasked
FROM defect_report
WHERE defect_Id = '82'`
Appreciate the guidance you guys give!
You are completely mixing up SQL dialects and even there are syntax errors.
Assuming you are talking about MS SQL Server let's try this:
SELECT defect_Id,
CASE WHEN DATEDIFF(DD, date_Investigaton, getdate()) >= priority
THEN 'YES'
ELSE 'NO'
END AS Overtasked
FROM <YourTable>
WHERE <YourWhereIfAny>
If date_Investigation is a DATE column, the subtraction date_Investigation - CURRENT_DATE() produces the number of days you need.
Otherwise (if it is a DATETIME, for example) both operands are converted to float and the result is something you are totally not expecting. For such situations use the DATEDIFF() function. It interprets its arguments as DATE (ignores the time part) and returns the integer number of days between the two dates.
Your query should be like:
SELECT
`defect_Id`,
IF (DATEDIFF(`date_Investigaton`, CURRENT_DATE()) >= `priority`, 'YES', 'NO')
AS `Overtasked`
FROM [...your table name here...]
WHERE [...conditions...]
Replace the parts in square brackets ([...]) with the name of the table where to get the data from and some conditions to limit the number of returned rows (otherwise it will get the entire table which, most probably, is not what you want).
Btw, CURRENT_DATE() is also a function. If you write it in backquotes (``), MySQL will try to find a column with this name and it will fail.
Read the accepted answer for this question. It explains when to use back ticks, single quotes or double quotes in MySQL (and partially in PHP).

Using DATE_SUB() based off dynamic field

How does one go abouts using a dynamically created field to be used within a DATE_SUB calculation?
I have this SQL below:
SELECT *,
CASE
WHEN `currentDate` IS NULL
THEN
`lastDate`
ELSE
`currentDate`
END AS `useDate`,
CASE
WHEN `type` = 'weekly'
THEN DATE_SUB(`useDate`, INTERVAL 1 WEEK)
END AS `nextDate`
FROM `aTable`
And this does not work, due to error '#1054 - Unknown column 'useDate' in 'field list''
The query works fine if I am using an actual field from the Select *, however won't accept the dynamically created field.
What would the proper way to work with this without having to do a 'case in case' query?
Did you try to use the CASE clause inside WHEN?
SELECT *,
CASE
WHEN `currentDate` IS NULL
THEN `lastDate`
ELSE `currentDate`
END AS `useDate`,
CASE
WHEN `type` = 'weekly'
THEN DATE_SUB(
CASE
WHEN `currentDate` IS NULL
THEN `lastDate`
ELSE `currentDate`
END AS `useDate`
, INTERVAL 1 WEEK)
END AS `nextDate`
FROM `aTable`

MySQL if then clause

I sum up the rows of two columns in two tables i.e. something like this:
SUM( tableA.age ) + sum( tableB.age) as 'Total Ages'
But in some cases the result of table A is null while result of table B is not. In this case I get as a total result null although it is something like "NULL + 45" which is not null actually. Therefore I thought it would be a good idea to use the if clause of the sql syntax. But it does not work I get an error when trying to do the following:
IF SUM( tableA.age ) IS NULL THEN 0 ELSE SUM( tableA.age ) END IF + IF SUM( tableB.age ) IS NULL THEN 0 ELSE SUM( tableB.age ) END IF
How would I do that in a proper way?
Simply use IFNULL() when you feel the field has NULL value.
SUM(IFNULL(tableA.age,0) )
You can use this MYSQL function.
Instead of the complex (and syntactically incorrect) IF statements, use COALESCE(), which returns its first non-null argument, and specify 0 as its second argument so it defaults to zero when the aggregate SUM() is null
COALESCE(SUM(tableA.age), 0) + COALESCE(SUM(tableB.age), 0)
Use IFNULL(column, 0) to convert the column value to zero:
SUM( IFNULL(tableA.age,0) ) + SUM( IFNULL(tableB.age,0) ) as 'Total Ages'