select is not valid at this position in SQLworkbench - mysql

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

Related

User-defined function sorting column problem

I have taken reference from the internet about one user-defined function to locate 'nth occurrence of a string to do the sort column name in the database. I am using MySQL 5.5 version, not the latest version. Here is my sample database link https://dbfiddle.uk/?rdbms=mysql_5.5&fiddle=bcb32a6b47d0d5b061fd401d0888bdc3
My problem is I want to sort column name in the database follow the prefix number, but I am using below the SQL query, it doesn't work.
select t.id,t.name
from
(
select t.*, cast((case when col1_col2_ref > 0
then
substring_index(modified_name,'-',1)
else
modified_name
end
) as unsigned) col1
, cast((case when col1_col2_ref > 0
and col3_ref > 0
then
substr(modified_name,(col1_col2_ref + 1),(col3_ref - (col1_col2_ref + 1)))
when col1_col2_ref > 0
then
substr(modified_name,(col1_col2_ref + 1))
end) as unsigned) col2
, cast((case when col3_ref > 0
and col4_ref > 0
then
substr(modified_name,(col3_ref + 1),(col4_ref - (col3_ref + 1)))
when col3_ref > 0
then
substr(modified_name,(col3_ref + 1))
end) as unsigned) col3
, cast((case when col4_ref > 0
then
substr(modified_name,(col4_ref + 1))
end) as unsigned) col4
from
(
select t.*,substring_index(name,' ',1) modified_name
,locate('-',name,1) col1_col2_ref
,locate('/',name,1) col3_ref
,locate('/',name,locate('/',name,1)+1) col4_ref
from filing_code_management t
) t
) t
order by col1,col2,col3,col4
It shows me below the result, it cannot sort properly.
Output 1
Actually I want the output sample like below:
Output 2
Output 3
This is before I can sort the column name link, https://dbfiddle.uk/?rdbms=mysql_5.5&fiddle=6b12a4d42359cb30f27a5bfb9d0c8210. After I am inserted into new data, it cannot work for me. Maybe an example in new data like this error (R)100-6-2-2 Mesyuarat Majlis Kerajaan Negeri (MMKN) JKK if I put () in front. Or in new data like this error 100-1-1 Penggubalan/Penyediaan/Pindaan Undang-Undang/Peraturan if I put / in between the word.
Hope someone can guide me to solve this problem. Thanks.
You should be able to adapt the following code to your needs (tested at your DB Fiddle!). I've used the file_name column instead of the name column to slightly simplify building the sort fields, as it seems the file name is always repeated in the first part of the name field anyway.
This would be quite a bit simpler using regular expression support, but I note that the version of MySQL you are using doesn't have this feature (I think it arrives in SQL 8.0, if I'm not mistaken).
SELECT id,
num_hyphens,
CAST(SUBSTRING_INDEX(CONCAT(file_name_adj,'-'), '-', 1) AS UNSIGNED) AS sort1,
CAST(CASE WHEN num_hyphens = 0
THEN '0'
ELSE SUBSTRING_INDEX(SUBSTRING_INDEX(file_name_adj,'-', 2), '-',-1)
END AS UNSIGNED) AS sort2,
CAST(CASE WHEN num_hyphens <= 1
THEN '0'
ELSE SUBSTRING_INDEX(SUBSTRING_INDEX(file_name_adj,'-', 3), '-',-1)
END AS UNSIGNED) AS sort3,
CAST(CASE WHEN num_hyphens <= 2
THEN '0'
ELSE SUBSTRING_INDEX(file_name_adj, '-', -1)
END AS UNSIGNED) AS sort4,
file_name,
name
FROM (
SELECT id, name, MID(file_name, instr(file_name, ')') + 1) AS file_name_adj, file_name,
LENGTH(file_name) - LENGTH(REPLACE(file_name, '-', '')) AS num_hyphens
FROM filing_code_management
) t1
ORDER BY sort1, sort2, sort3, sort4

Using CASE in WHERE Statement when parameter has multiple values

I have a problem which I think relates to having a multiple value parameter.
In my TblActivity there are two fields TblActivity.ActivityServActId and TblActivity.ActivityContractId which I want to include in my WHERE statement.
Filtering by these is optional. If the user selects 'Yes' for the parameter #YESNOActivity, then I want to filter the query looking for rows where TblActivity.ActivityServActId matches one of the options in the parameter #ServiceActivity.
The same goes for the #YESNOContract, TblActivity.ActivityContractId and #Contract respectively
I managed to get to this:
WHERE
(CASE WHEN #YESNOActivity = 'Yes' THEN TblActivity.ActivityServActId ELSE 0 END)
IN (CASE WHEN #YESNOActivity = 'Yes' THEN #ServiceActivity ELSE 0 END)
AND (CASE WHEN #YESNOContract = 'Yes' THEN TblActivity.ActivityContractId ELSE 0 END)
IN (CASE WHEN #YESNOContract = 'Yes' THEN #Contract ELSE 0 END)
However, although this code works fine if there is only one value selected in the parameter #ServiceActivity or #Contract, as soon as I have more than one value in these parameters, I get the error:
Incorrect syntax near ','.
Query execution failed for dataset 'Activity'. (rsErrorExecutingCommand)
An error has occurred during report processing. (rsProcessingAborted)
Can anyone see what I'm doing wrong? I could understand it if I had an = instead of IN in the WHERE statement but can't figure this one out.
Using SQL Server 2008 and SSRS 2008-r2
If your #ServiceActivity is something like 1,2,3
You can do something like this
WHERE `,1,2,3,` LIKE `%,1,%`
So you format your variables
WHERE ',' + #ServiceActivity + ',' LIKE '%,' + ID + ',%'
SQL FIDDLE DEMO
SELECT *
FROM
(SELECT '1,2,3,4' as X UNION ALL
SELECT '2,3,4,5' as X UNION ALL
SELECT '3,4,5,6' as X UNION ALL
SELECT '1,3,4,5' as X
) as T
WHERE ',' + X + ',' LIKE '%,1,%'
For Your Case
(CASE WHEN #YESNOActivity = 'Yes'
THEN ',' + #ServiceActivity + ','
ELSE NULL
END)
LIKE
(CASE WHEN #YESNOActivity = 'Yes'
THEN '%,' + TblActivity.ActivityServActId + ',%'
ELSE 0
END)
In SQL, the IN clause does not support parameters the way you are using them. The general syntax is
IN (1, 2, 3, 4)
you have
IN (#Param)
where something like
#Param = '1, 2, 3, 4'
Internally, SQL will turn this into
IN ('1, 2, 3, 4')
Note the quotes... you are now matching against a string!
There are a number of ways to address this. Search SO for "sql in clause parameter", pick one that works for you, and upvote it.
(Added)
Parameterize an SQL IN clause seems pretty definitive on the subject. While long ago I upvoted the third reply (the one with table-value parameters), any of the high-vote answers could do the trick. The ideal answer depends on the overall problem you are working with. (I am not familiar with SSRS, and can't give more specific advice.)
So after a lot of messing around I put together a simple workaround for this by dropping my use of CASE altogether - but I have a suspicion that this is not a terribly efficient way of doing things.
WHERE
(#YESNOActivity = 'No' OR (#YESNOActivity = 'Yes' AND
TblActivity.ActivityServActId IN (#ServiceActivity)))
AND
(#YESNOContract = 'No' OR (#YESNOContract = 'Yes' AND
TblActivity.ActivityContractId IN (#Contract)))

How to check negative values in mysql and decide the output after that

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;

Using CASE Function with DATEDIFF and COUNT

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

Update Database field value by Alphabetical order

Reorder rows
A row in my database it in a random order with the following characters
HFMNLBX#&I
It was input weirdly and the rows are like HF and FH, which are both equivalent to the system. Is there a way to update all of the rows to go in alphabetical order, then the characters on the end?
Thanks
Here is a way to alphabetize the characters in a column:
select concat((case when col like '%A%' then 'A' else '' end),
(case when col like '%B%' then 'B' else '' end),
. . .
(case when col like '%Z%' then 'Z' else '' end)
) as newcol
from t
Note that this does not handle duplicate letters.
I'm not sure exactly what you mean by "characters on the end". You can use a subquery, for instance, to handle just a subset of them.
Or, if you want to keep everything after the #, something like:
select concat((case when col like '%A%#%' then 'A' else '' end),
(case when col like '%B%#%' then 'B' else '' end),
. . .
(case when col like '%Z%#%' then 'Z' else '' end),
substring(col, locate('#', col) - 1)
) as newcol
from t