So I have this query with LOCATE function:
SELECT TRIM(CASE WHEN store_name like "%|%" THEN LEFT(store_name, LOCATE('|', store_name) - 1) ELSE
CASE WHEN store_name like "%,%" THEN LEFT(store_name, LOCATE(',', store_name) - 1) ELSE
CASE WHEN store_name like "% - %" THEN LEFT(store_name, LOCATE(' - ', store_name) - 1) ELSE
store_name
END
END
END)
Everything is working, but I need to change from MySQL to Bigquery now. When I tried to paste this query in Bigquery editor, I got an error: Function not found: LOCATE at [3:76]
There are different similar functions to Locate using BigQuery such as REGEXP_EXTRACT[1], as the INSTR [2], or SUBSTR[3] function.
[1]https://cloud.google.com/bigquery/docs/reference/legacy-sql#regularexpressionfunctions
[2]https://cloud.google.com/bigquery/docs/reference/standard-sql/string_functions#instr
[3]https://cloud.google.com/bigquery/docs/reference/standard-sql/functions-and-operators#substr
Consider below approach (using REGEXP_EXTRACT_ALL)
select regexp_extract_all(store_name, r'(.*?)(?:,| - |\|)')[offset(0)]
if applied to dummy data - output is as below
Related
I would like to write a query using IF, but its not working , what's wrong with this query?
SELECT
IF(Emp.Name is not null)
((Emp.Name) + '_' + (Emp.LastName)) as ID
else
Emp.ID
I get this error:
Incorrect syntax near the keyword 'IF'.
Why is that?
Thank you.
You can use CASE EXPRESSION :
SELECT CASE WHEN emp.name is not null THEN emp.name + '_' + emp.lastName
ELSE Emp.id
END as [ID]
FROM ...
The IF() is performed differently in SQL-Server (I assume by the concat syntax),
IF ( Condition )
SQL STATEMENT
ELSE
SQL STATEMENT
Which means you need to perform the entire select in each block. Your kind of IF() is used in MySQL , IF(Condition , THEN , ELSE )
Try using Case in your query check this MySQL: CASE Function
You need to do this in a CASE clause:
SELECT
CASE WHEN (Emp.Name IS NOT NULL)
THEN ((Emp.Name) + '_' + (Emp.LastName))
ELSE
Emp.ID
END as ID
The IF..ELSE syntax is somewhat different:
IF(Emp.Name IS NOT NULL)
SELECT ((Emp.Name) + '_' + (Emp.LastName)) AS ID
ELSE
SELECT Emp.ID AS ID
Assuming it's SQL Server based on your syntax use this:
SELECT CASE <variable> WHEN <value> THEN <returnvalue>
WHEN <othervalue> THEN <returnthis>
ELSE <returndefaultcase>
END AS <newcolumnname>
FROM <table>
Instead of usinf IF, you can use CASE in SELECT statement. Something like this
SELECT
CASE Emp.Name
WHEN NULL THEN Emp.ID
ELSE CONCAT(CONCAT(Emp.Name,'_'),Emp.LastName)
END AS "ID"
FROM Emp;
Hope it helps.
I have the following rows:
http://domain1.com/moshe
https://domain2.com/
https://domain3.com
https://domain4.com?gembom
I need these results
domain1.com
domain2.com
domain3.com
domain4.com
How exactly can I do it in MySQL?
In JavaScript, I can simply use regex:
string.match(/https?:\/\/([^/]+)/)[0]
But I found, that MySQL doesn't have extracting regex. Is there an alternative way to achieve the same results?
Here is an example of how to extract the domain names from urls in MySQL,
DECLARE #WebUrl VARCHAR(35);
SET #WebUrl = 'http://stackoverflow.com/questions/ask?title=trim'
SELECT #WebUrl AS 'WebsiteURL',
LEFT(SUBSTRING(#WebUrl,
(CASE WHEN CHARINDEX('//',#WebUrl)=0
THEN 5
ELSE CHARINDEX('//',#WebUrl) + 2
END), 35),
(CASE
WHEN CHARINDEX('/', SUBSTRING(#WebUrl, CHARINDEX('//', #WebUrl) + 2, 35))=0
THEN LEN(#WebUrl)
else CHARINDEX('/', SUBSTRING(#WebUrl, CHARINDEX('//', #WebUrl) + 2, 35))- 1
END)
) AS 'Domain
';
You can make suitable modifications to suit your needs.
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)))
I've looked through a few different post trying to find a solution for this. I have a column that contains descriptions that follow the following format:
String<Numeric>
However the column isn't limited to one set of the previous mentioned format it could be something like
UNI<01> JPG<84>
JPG<84> UNI<01>
JPG<84>
UNI<01>
And other variations without any controlled pattern.
What I am needing to do is extract the number between <> into a separate column in another table based on the string before the <>. So UNI would qualify the following numeric to go to a certain table.column, while JPG would qualify to another table etc. I have seen functions to extract the numeric but not qualifying and only pulling the numeric if it is prefaced with a given qualifier string.
Based on the scope limitation mentioned in the question's comments that only one type of token (Foo, Bar, Blat, etc.) needs to be found at a time: you could use an expression in a Derived Column to find the token of interest and then extract the value between the arrows.
For example:
FINDSTRING([InputColumn], #[User::SearchToken] + "<", 1) == 0)?
NULL(DT_WSTR, 1) :
SUBSTRING([InputColumn],
FINDSTRING([InputColumn], #[User::SearchToken] + "<", 1)
+ LEN(#[User::SearchToken]) + 1,
FINDSTRING(
SUBSTRING([InputColumn],
FINDSTRING([InputColumn], #[User::SearchToken] + "<", 1)
+ LEN(#[User::SearchToken]) + 1,
LEN([InputColumn])
), ">", 1) - 1
)
First, the expression checks whether the token specified in #[User::SearchToken] is used in the current row. If it is, SUBSTRING is used to output the value between the arrows. If not, NULL is returned.
The assumption is made that no token's name will end with text matching the name of another token. Searching for token Bar will match Bar<123> and FooBar<123>. Accommodating Bar and FooBar as distinct tokens is possible but the requisite expression will be much more complex.
You could use an asynchronous Script Component that outputs a row with type and value columns for each type<value> token contained in the input string. Pass the output of this component through a Conditional Split to direct each type to the correct destination (e.g. table).
Pro: This approach gives you the option of using one data flow to process all tag types simultaneously vs. requiring one data flow per tag type.
Con: A Script Component is involved, which it sounds like you'd prefer to avoid.
Sample Script Component Code
private readonly string pattern = #"(?<type>\w+)<(?<value>\d+)>";
public override void Input0_ProcessInputRow(Input0Buffer Row)
{
foreach (Match match in Regex.Matches(Row.Data, pattern, RegexOptions.ExplicitCapture))
{
Output0Buffer.AddRow();
Output0Buffer.Type = match.Groups["type"].Value;
Output0Buffer.Value = match.Groups["value"].Value;
}
}
Note: Script Component will need an output created with two columns (perhaps named Type and Value) and then have the output's SynchronousInputID property set to None).
I ended up writing a CTE for a view to handle the data manipulation and then handled the joins and other data pieces in the SSIS package.
;WITH RCTE (Status_Code, lft, rgt, idx)
AS ( SELECT a.Status_code
,LEFT(a.Description, CASE WHEN CHARINDEX(' ', a.Description)=0 THEN LEN(a.Description) ELSE CHARINDEX(' ', a.Description)-1 END)
,SUBSTRING(a.Description, CASE WHEN CHARINDEX(' ', a.Description)=0 THEN LEN(a.Description) ELSE CHARINDEX(' ', a.Description)-1 END + 1, DATALENGTH(a.Description))
,0
FROM [disp] a WHERE NOT( Description IS NULL OR Description ='')
UNION ALL
SELECT r.Status_Code
,CASE WHEN CHARINDEX(' ', r.rgt) = 0 THEN r.rgt ELSE LEFT(r.rgt, CHARINDEX(' ', r.rgt) - 1) END
,CASE WHEN CHARINDEX(' ', r.rgt) > 0 THEN SUBSTRING(r.rgt, CHARINDEX(' ', r.rgt) + 1, DATALENGTH(r.rgt)) ELSE '' END
,idx + 1
FROM RCTE r
WHERE DATALENGTH(r.rgt) > 0
)
SELECT Status_Code
-- ,lft,rgt -- Uncomment to see whats going on
,SUBSTRING(lft,0, CHARINDEX('<',lft)) AS [Description]
,CASE WHEN ISNUMERIC(SUBSTRING(lft, CHARINDEX('<',lft)+1, LEN(lft)-CHARINDEX('<',lft)-1)) >0
THEN CAST (SUBSTRING(lft, CHARINDEX('<',lft)+1, LEN(lft)-CHARINDEX('<',lft)-1) AS INT) ELSE NULL END as Value
FROM RCTE
where lft <> ''
This is my SQL query
DECLARE #strManualRefundIdList AS VARCHAR(MAX)
SELECT #strManualRefundIdList = COALESCE(#strManualRefundIdList + '|', '') + CONVERT(VARCHAR(MAX), ManualRefund_strReasonCode)
FROM tblManualRefunds WHERE ManualRefund_lngId IN ( 20 ,21 ,22 )
SELECT #strManualRefundIdList;
This gives like pivot, all the rows concatenated in a single row.
The Same i need to convert into MySql Query.
I tried like this
SELECT
CONCAT(COALESCE(CONCAT(v_strManualRefundIdList, '|'), '') , ( ManualRefund_lngId))
INTO
v_strManualRefundIdList
FROM tblManualRefunds
WHERE Trans_lngId IN ( 20 ,21 ,22 ) ;
But it throws error as Error Code: 1172. Result consisted of more than one row
How to translate that query. I am new to database.
Please help me in figuring out this.
UPDATE :
The way i found out was assigning into a cursor and loop through and concatenate it.
But is that the only way ? or any better way is available ?
SELECT group_concat(ManualRefund_strReasonCode SEPARATOR '|')
FROM tblManualRefunds
WHERE manualRefund_lngId in (20,21,22)
SQL Fiddle
As per xQbert Comment i tried this
SELECT
GROUP_CONCAT(COALESCE(CONCAT('shan', '|'), '') , ( ManualRefund_lngId))
INTO
#v_strManualRefundIdList
FROM tblManualRefunds ;
Its working fine.
Thanks Man.. !!!