Hi I'm sure this is a simple fix but I cannot figure it out. I'm trying to label records that are overdue the completion date (CompleteDate-CurrentDate) (these numbers will be negatives) to "Overdue" for a report. I would also like the records to not be altered for the numbers that are not negatives. Here is a snippet of the code which is currently giving me NULL entries
Select CASE DATEDIFF(targetcompletedate, NOW())
When count(*) <=0 then 'Overdue'
END 'Days Left',
Any help would be greatly appreciated
Thanks
There are two variants of CASE:
CASE
WHEN condition1 THEN result1
WHEN condition2 THEN result2
...
ELSE result_else
END
CASE scalar_expression
WHEN value1 THEN result1
WHEN value2 THEN result2
...
ELSE result_else
END
In your case, it should be the first syntax, because you are not comparing to specific values but to a range. Instead, your query is actually using the second syntax. The count(*)<=0 expression is evaluated to a boolean which is then implicitly converted to an integer, the type implied by the DATEDIFF result.
You just need to use the first syntax, something like this:
select case when targetcompletedate is null
then 'Not set'
when DATEDIFF(targetcompletedate, NOW()) <= 0
then 'Overdue'
else DATEDIFF(targetcompletedate, NOW())
end as 'Days Left'
I would suggest that you eliminate the datediff() entirely:
Select (CASE when targetcompletedate <= NOW() the 'Overdue' else 'Days Left' end)
If you want to show things as numbers, then you want the datediff(). For clarity, I would explicitly convert to character strings:
select (case when targetcompletedate <= NOW() then 'Overdue'
else cast(DATEDIFF(targetcompletedate, NOW()) as varchar(255))
end)
Or, perhaps:
select (case when targetcompletedate <= NOW() then 'Overdue'
else concat(DATEDIFF(targetcompletedate, NOW()), ' days left')
end)
The philosophy being: don't use a function if there is a simpler and clearer way to express what you want.
However, I wonder if you want to count the number in each group:
select sum(case when targetcompletedate <= NOW() then 1 else 0 end) as NumOverdue,
sum(case when targetcompletedate <= NOW() then 0 else 1 end) as NumWithDaysLeft
Just try this code:
SELECT
CASE
WHEN datediff(dd,targetcompletedate,now()) <= 0 THEN 'Overdue'
WHEN datediff(dd,targetcompletedate,now()) > 0 THEN 'Days_left'
ELSE NULL END,
datediff(dd,targetcompletedate,now()) AS 'days'
FROM tablename
The output is like:
Overdue -23
Days_left 13
Related
When I execute following sql, the error returned
select is not valid at this position for this server version , expecting for, lock, table,values, with, '('
My sql like following.
select
id
,COALESCE(count(*) FILTER (WHERE snapshot_day in ('2021-04-19')), 0) AS "2021-04-19"
,COALESCE(count(*) FILTER (WHERE snapshot_day in ('2021-04-20')), 0) AS "2021-04-20"
,COALESCE(count(*) FILTER (WHERE snapshot_day in ('2021-04-21')), 0) AS "2021-04-21"
from table
where type in ('Daily')
group by 1
I checked my query but I couldn't find any mistakes..
Where is the problems?
If someone has opinion,please let me know
Thanks
As mentioned, there is no FILTER in mysql but you can still achieve the same effect with something like this:
select
id
,coalesce(sum(case when snapshot_day in ('2021-04-19') then 1 else 0 end), 0) AS "2021-04-19"
,coalesce(sum(case when snapshot_day in ('2021-04-20') then 1 else 0 end), 0) AS "2021-04-20"
,coalesce(sum(case when snapshot_day in ('2021-04-21') then 1 else 0 end), 0) AS "2021-04-21"
from table
where type in ('Daily')
group by 1
I have some code that converts numbers from Hexadecimal to Decimal, and checks to see if greater than or equal to. Today, I discovered this doesn't always work, and I have no idea why.
I have tried using the raw values, and that works. Conversions outside of the compare work.
select case when 5 >= 40 then 'Fail' else 'Pass' end as 'Check';
select case WHEN CONV('0005',16,10) >= CONV('28',16,10) THEN 'Fail' else 'Pass' end as 'Check';
select CONV('0005',16,10) as '1', CONV('28',16,10) as '2';
The first select works as intended (Pass). The second select does not. The third select just shows that the conversion is working properly (i.e. 0005 HEX = 5 Decimal, and 28 Hex = 40 Decimal).
What am I missing?
From the docs:
CONV(N,from_base,to_base)
... Returns a string representation of the
number N ...
The results are strings and compared as such. For strings '5' > '40'. So you need to cast the ressults either explicitly with CAST
select case
WHEN CAST(CONV('0005',16,10) as SIGNED) >= CAST(CONV('28',16,10) as SIGNED )
THEN 'Fail'
else 'Pass' end
as 'Check';
or implicitly with a numeric operation like +0
select case WHEN CONV('0005',16,10)+0 >= CONV('28',16,10)+0 THEN 'Fail' else 'Pass' end as 'Check';
If you know the max length of the HEX strings, you could also fill them with zeros using LPAD()
select case
WHEN lpad('0005', 20, 0) >= lpad('28', 20, 0)
THEN 'Fail'
else 'Pass'
end as 'Check';
What is the most efficient way to create a dynamic sp where im checking the param NAME either its null or has value.
my GOAL here is to select the specific name and their datas else just display all name with datas if param NAME is null or has no value submitted.
Here's my 2 solution:
option 1
IF (SELECT call_transactions.`called_name` IS NULL FROM call_transactions) THEN
SELECT a.`called_name` , DATE_FORMAT(a.`start_datetime`,"%m/%d/%Y %T") AS start_datetime , DATE_FORMAT(a.`end_datetime`,"%m/%d/%Y %T") AS end_datetime, SEC_TO_TIME(a.`duration`) AS duration
FROM call_transactions a
WHERE a.`user_id` = pUSERID AND a.duration <> 0 AND DATE_FORMAT(a.start_datetime , "%m/%d/%Y") BETWEEN pSTART AND pEND
ORDER BY a.start_datetime DESC;
ELSE
SELECT a.`called_name` , DATE_FORMAT(a.`start_datetime`,"%m/%d/%Y %T") AS start_datetime , DATE_FORMAT(a.`end_datetime`,"%m/%d/%Y %T") AS end_datetime, SEC_TO_TIME(a.`duration`) AS duration
FROM call_transactions a
WHERE a.`user_id` = pUSERID AND a.called_name = pNAME AND a.duration <> 0 AND DATE_FORMAT(a.start_datetime , "%m/%d/%Y") BETWEEN pSTART AND pEND
ORDER BY a.start_datetime DESC;
END IF;
option 2
SELECT a.`called_name` , DATE_FORMAT(a.`start_datetime`,"%m/%d/%Y %T") AS start_datetime , DATE_FORMAT(a.`end_datetime`,"%m/%d/%Y %T") AS end_datetime, SEC_TO_TIME(a.`duration`) AS duration
FROM call_transactions a
WHERE a.`user_id` = pUSERID AND (a.called_name = pNAME OR pNAME = '') AND a.duration <> 0 AND DATE_FORMAT(a.start_datetime , "%m/%d/%Y") BETWEEN pSTART AND pEND
ORDER BY a.start_datetime DESC;
Thank you in advance for the enlightenment guys. Just a curious kid here
Use your 2nd option, but test for the correct value.
WHERE a.`user_id` = pUSERID
AND (pNAME IS NULL OR a.called_name = pNAME)
AND a.duration <> 0 AND DATE_FORMAT(a.start_datetime , "%m/%d/%Y") BETWEEN pSTART AND pEND
In the second condition, note that I reversed the terms.
This is not strictly necessary, because the optimizer should prune away whichever condition is unnecessary, but this makes your short-circuit intentions clear.
Note also that NULL is not equivalent to empty string, and nothing is equal to NULL, so IS NULL should be used if NULL is what you are matching against.
I don't know what you're doing with DATE_FORMAT() here, but don't do that.
Use correct datetimes everywhere, or use STR_TO_DATE() to convert the parameters, not DATE_FORMAT() against the column. You can't compare mm/dd/yyyy "between" two values. That doesn't make sense. 12/09/2010 is "between" 12/08/2017 and 12/10/2017 because your code is comparing strings, lexcally, not comparing dates.
As a rule, you should never use a column as an argument to function in WHERE because this defeats any indexes on the column and forces a full scan.
I am using a mysql case for some calculation and my demand is that if the output is negative then i will show 0 in the place of the negative column.Otherwise the positive value.
Let me post the query:
select
concat(jo.title,' (', CCP.name, ')'), PL.analyst, PL.consultant,
PL.csm,
(CASE
WHEN PL.productType like 'Staffing' THEN (SELECT ((DATEDIFF(PL.dateEnd, PL.dateClientEffective)) -((WEEK(PL.dateEnd) - WEEK(PL.dateClientEffective)) * 2) - (case when weekday(PL.dateEnd) = 6 then 1 else 0 end) - (case when weekday(PL.dateClientEffective) = 5 then 1 else 0 end)) as DifD) * 8 * (PL.clientBillRate-PL.payRate) ELSE (PL.salary*PL.fee)END) Value
Now if the value is negative, then it should show 0 else will show the original value
The simplest way is simply to use greatest():
select greatest(<expression>, 0) as col
It is unclear what column/expression you want to do this for in your query. But, you can just plug it in.
The advantage of this method over other methods is:
The only needs to appear once in the query. Not having to duplicate code reduces the likelihood of errors.
There is no need for a subquery. This is an issue in MySQL only because MySQL materializes subqueries.
Simply use SIGN() in mysql
It returns 1 as a positive value and -1 is a negative value
Example
SELECT SIGN(500); -- (Output is 1)
SELECT SIGN(2500); -- (Output is 1)
SELECT SIGN(-999); -- (Output is -1)
SELECT SIGN(-5); -- (Output is -1)
please check this, haven't tested yet.
Note: this might not be the best solution
select concat(jo.title,' (', CCP.name, ')'), PL.analyst, PL.consultant, PL.csm,
if(
(CASE WHEN PL.productType like 'Staffing' THEN (SELECT ((DATEDIFF(PL.dateEnd, PL.dateClientEffective)) -((WEEK(PL.dateEnd) - WEEK(PL.dateClientEffective)) * 2) -
(case when weekday(PL.dateEnd) = 6 then 1 else 0 end) -
(case when weekday(PL.dateClientEffective) = 5 then 1 else 0 end)) as DifD) * 8 * (PL.clientBillRate-PL.payRate) ELSE (PL.salary*PL.fee)END)
< 0,0,
(CASE WHEN PL.productType like 'Staffing' THEN (SELECT ((DATEDIFF(PL.dateEnd, PL.dateClientEffective)) -((WEEK(PL.dateEnd) - WEEK(PL.dateClientEffective)) * 2) -
(case when weekday(PL.dateEnd) = 6 then 1 else 0 end) -
(case when weekday(PL.dateClientEffective) = 5 then 1 else 0 end)) as DifD) * 8 * (PL.clientBillRate-PL.payRate) ELSE (PL.salary*PL.fee)END)
) Value
Just do like this :
select temp.* , --all your columns
if(temp.value<0,0,temp.value) as Value
from
( your query mentioned above) temp;
This UPDATE fails with the error "Truncated incorrect DOUBLE value: '-'" and I cannot figure out why.
UPDATE psych
SET pdqp_adm=CAST((CAST(pdqt_adm AS SIGNED)) - (CAST(pdqf_adm AS SIGNED)) AS CHAR)
WHERE pdqt_adm>0
AND pdqt_adm IS NOT NULL
AND pdqf_adm>0
AND pdqf_adm IS NOT NULL
AND pdqt_adm>=pdqf_adm
All of the columns used here (pdqp_adm, pdqt_adm, pdqf_adm) are VARCHAR(6). I can do this query and the calculation works just fine:
SELECT CAST((CAST(pdqt_adm AS SIGNED)) - (CAST(pdqf_adm AS SIGNED)) AS CHAR)
FROM psych
WHERE pdqt_adm>0
AND pdqt_adm IS NOT NULL
AND pdqf_adm>0
AND pdqf_adm IS NOT NULL
AND pdqt_adm>=pdqf_adm
Ok, this error had nothing to do with the calculated values.
When I run this, I get this same error (only for record with ID 4972):
SELECT p.id, p.pdqt_adm, p.pdqf_adm
FROM psych p
WHERE p.pdqt_adm>0
AND p.pdqt_adm IS NOT NULL
AND p.pdqf_adm>0
AND p.pdqf_adm IS NOT NULL
AND p.id=4972
As it turns out, the 2 columns being used to compare to 0 and to each other both contain the value "-". Now, why this does not affect my SELECT in my question above, but does affect my UPDATE...I have no idea.
The update and select do not necessarily process the table in the same order. You can try:
UPDATE psych
SET pdqp_adm=CAST((CAST(pdqt_adm AS SIGNED)) - (CAST(pdqf_adm AS SIGNED)) AS CHAR)
WHERE (case when pdqt_adm <> '-' then pdqt_adm else 0 end) > 0 AND
pdqt_adm IS NOT NULL AND
(case when pdqf_adm <> '-' then pdqf_adm else 0 end) > 0 AND
pdqf_adm IS NOT NULL AND
(case when pdqt_adm <> '-' then pdqt_adm else 0 end) >= (case when pdqf_adm <> '-' then pdqf_adm else 0 end);