I have a string like
ADN120_XK7760069988881LJ
in one of my columns. I have to extract the number with 13 digits length. For example, in the above case, I want to extract 7760069988881 in SQL Server.
using patindex() with substring() (using a variable for the pattern and replicate() to simplify repeating [0-9] 13 times):
create table t (val varchar(128));
insert into t values ('ADN120_XK7760069988881LJ');
declare #pattern varchar(128) = '%'+replicate('[0-9]',13)+'%';
select substring(val,patindex(#pattern,val),13)
from t;
rextester demo: http://rextester.com/MOEVG64754
returns 7760069988881
Creating TEMP table with your query
SELECT 'ADN120_XK7760069988881LJ' CODE INTO #TEMP
Solution using regular expression
SELECT SUBSTRING(CODE,PATINDEX('%[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]%',CODE),13)
FROM #TEMP
Couldn't reduce the number of times [0-9] used
Hope this helps
Related
I'm trying to insert comma separated Guids into a temp table, to later check for a value using IN in these Guids. The following query is inserting only the first value in the table twice.
DECLARE #campaignids nvarchar(max) = '1DEBD122-FF1B-4E87-8812-D427ABA5D54E,FBD06A2E-24D1-4C06-B71D-B4306D8EA3BD'
DECLARE #TempCampaignIds TABLE (CampaignId uniqueidentifier)
INSERT INTO #TempCampaignIds
SELECT CAST(#campaignids AS uniqueidentifier)
FROM STRING_SPLIT(#campaignids, ',')
SELECT CampaignId FROM #TempCampaignIds
--result
CampaignId
1DEBD122-FF1B-4E87-8812-D427ABA5D54E
1DEBD122-FF1B-4E87-8812-D427ABA5D54E
You need to use the value from the string:
INSERT INTO #TempCampaignIds (CampaignId)
SELECT CAST(s.value AS uniqueidentifier)
FROM STRING_SPLIT(#campaignids, ',') s;
Here is a db<>fiddle.
I'm actually surprised that your code works, but SQL Server converts the first value of such a string without an error. That doesn't seem to happen for other data types. In fact, SQL Server appears to look at only the first 36 characters for a unique identifier.
In SQL HANA, I need to find how many times a given word is repeated in a string column whose values are delimited by "," and output it as a separate column.
Example, the string column contains:
ZN,ZN,ZS,ZQ
Expected result for "ZN":
2
You might find it acceptable to search only the string ZN by ignoring the fact that there's a comma.
You may count the number of occurrences of any substring by using the string function OCCURRENCES_REGEXPR:
SELECT OCCURRENCES_REGEXPR('(ZN)' IN STRINGCOLUMN) "occurrences_zn" FROM TABLE;
If you really want to clearly specify that ZN is to be searched as an entire word between commas or at the edges, then you may find a better regular expression (the question is then more about regular expressions and not SQL HANA, and you may find existing answers in Stack Overflow).
I can't remember where I found the trick, but in SQL Server, the following works like a charm:
DECLARE #myStringToSearch nvarchar(250) = 'ZN,ZN,ZS,ZQ'
DECLARE #searchValue nvarchar(5) = 'ZN'
SELECT (LEN(#myStringToSearch) - LEN(REPLACE(#myStringToSearch, #searchValue, ''))) / LEN(#searchValue)
The last line compares the length of the original string with the length of the same string, but this time replacing your search value (ZN) with a blank string. In our case, this would result in 4, because ZN is 2 characters, and it was removed twice. However, we're not interested in how many characters were removed, but in how many times the value was encountered, so we divide that result by the length of your search string (2).
Output of the query:
2
You could easily implement this as a DEFAULT constraint in your table, provided your search string is the same across every row.
I wrote one anonymous block in sql , which can be converted to HANA Table function and can be used to achieve expected result.
DO
BEGIN
DECLARE FULL_STRING VARCHAR(100);
DECLARE TRIM_STRING VARCHAR(100);
DECLARE VAL_STRING VARCHAR(100);
FULL_STRING ='ZN,ZN,ZS,ZQ';
FULL_STRING=CONCAT(FULL_STRING,',');
--SELECT :FULL_STRING FROM DUMMY;
VAL_STRING=SUBSTRING(:FULL_STRING,1,LOCATE(:FULL_STRING,',',1)-1);
VAR_TABLE=SELECT :VAL_STRING STRINGVAL FROM DUMMY;
TRIM_STRING=SUBSTRING(:FULL_STRING,LOCATE(:FULL_STRING,',',1)+1 ,LENGTH(:FULL_STRING));
--SELECT * FROM :VAR_TABLE;
--SELECT :TRIM_STRING FROM DUMMY;
WHILE :TRIM_STRING IS NOT NULL AND LENGTH(:TRIM_STRING)>0
DO
VAL_STRING=SUBSTRING(:TRIM_STRING,1,LOCATE(:TRIM_STRING,',',1)-1);
--SELECT :VAL_STRING FROM DUMMY;
VAR_TABLE=SELECT STRINGVAL FROM :VAR_TABLE
UNION ALL
SELECT :VAL_STRING FROM DUMMY;
TRIM_STRING=SUBSTRING(:TRIM_STRING,LOCATE(:TRIM_STRING,',',1)+1 ,LENGTH(:TRIM_STRING));
--i=i+1;
--SELECT :TRIM_STRING FROM DUMMY;
END WHILE ;
SELECT STRINGVAL,COUNT(STRINGVAL) FROM :VAR_TABLE GROUP BY STRINGVAL;
--SELECT :TRIM_STRING FROM DUMMY;
I have a column (XID) that contains a varchar(20) sequence in the following format: xxxzzzzzz Where X is any letter or a dash and zzzzz is a number.
I want to write a query that will strip the xxx and evaluate and return which is the highest number in the table column.
For example:
aaa1234
bac8123
g-2391
After, I would get the result of 8123
Thanks!
A bit painful in SQL Server, but possible. Here is one method that assumes that only digits appear after the first digit (which you actually specify as being the case):
select max(cast(stuff(col, 1, patindex('%[0-9]%', col) - 1, '') as float))
from t;
Note: if the last four characters are always the number you are looking for, this is probably easier to do with right():
select max(right(col, 4))
Using Numbers table
declare #string varchar(max)
set #string='abc1234'
select top 1 substring(#string,n,len(#string))
from
numbers
where n<=len(#string)
and isnumeric(substring(#string,n,1))=1
order by n
Output:1234
Using PATINDEX you can achieve it, like this -
DECLARE #test table
(
id INT,
player varchar(100)
)
INSERT #test
VALUES (1,'aaa1234'),
(2,'bac8123'),
(3,'g-2391')
SELECT
MAX(CONVERT(INT, LTRIM(SUBSTRING(player, PATINDEX('%[0-9]%', player), LEN(player)))))
FROM #test
Try:
Select MAX(RIGHT(XID,17))
from table
You can also use this method
CREATE TABLE #Tmp
(
XID VARCHAR(20)
)
INSERT INTO #Tmp(XID)
VALUES ('aaa1234'), ('bac8123'), ('g-2391')
SELECT MAX(RIGHT(XID, LEN(XID) - 3))
FROM #Tmp
I need to replace a list of characters in a string with some mapped characters.
I have a table 'dbo.CharacterMappings' with 2 columns: 'CharacterToFilter' and 'ReplacementCharacter'.
Say that there are 3 records in this table:
Filter Replacement
$ s
# a
0 o
How would I replace all of the filter characters in a string based on these mappings?
i.e. 'Hell0 c#t$' needs to become 'Hello cats'.
I cant really think of any way of doing this without resorting to a table variable and then looping through it. I.e. have a table variable with a 'count' column then use a loop to select 1 row at a time based on this column. Then I can use the REPLACE function to update the characters one at a time.
Edit: I should note that I always want to strip out these characters (I don't need to worry about $5 -> s5 for example).
declare #s varchar(50)= 'Hell0 c#t$'
select #s = REPLACE(#s, CharacterToFilter, ReplacementCharacter)
from CharacterMappings
select #s
You could create a function:
CREATE FUNCTION [dbo].[ReplaceAll]
(
#text varchar(8000)
)
RETURNS VARCHAR(8000)
AS
BEGIN
SELECT #text =
REPLACE(#text,cm.Filter, cm.Replacement)
FROM CharacterMappings cm;
RETURN #text
END
Then this
select dbo.[ReplaceAll]('Hell0 c#t$');
returns Hello cats
I have a row of strings that are in the following format:
'Order was assigned to lastname,firsname'
I need to cut this string down into just the last and first name but it is always a different name for each record.
The 'Order was assigned to' part is always the same.......
Thanks
I am using SQL Server. It is multiple records with different names in each record.
In your specific case you can use something like:
SELECT SUBSTRING(str, 23) FROM table
However, this is not very scalable, should the format of your strings ever change.
If you are using an Oracle database, you would want to use SUBSTR instead.
Edit:
For databases where the third parameter is not optional, you could use SUBSTRING(str, 23, LEN(str))
Somebody would have to test to see if this is better or worse than subtraction, as in Martin Smith's solution but gives you the same result in the end.
In addition to the SUBSTRING methods, you could also use a REPLACE function. I don't know which would have better performance over millions of rows, although I suspect that it would be the SUBSTRING - especially if you were working with CHAR instead of VARCHAR.
SELECT REPLACE(my_column, 'Order was assigned to ', '')
For SQL Server
WITH testData AS
(
SELECT 'Order was assigned to lastname,firsname' as Col1 UNION ALL
SELECT 'Order was assigned to Bloggs, Jo' as Col1
)
SELECT SUBSTRING(Col1,23,LEN(Col1)-22) AS Name
from testData
Returns
Name
---------------------------------------
lastname,firsname
Bloggs, Jo
on MS SQL Server:
declare #str varchar(100) = 'Order was assigned to lastname,firsname'
declare #strLen1 int = DATALENGTH('Order was assigned to ')
declare #strLen2 int = len(#str)
select #strlen1, #strLen2, substring(#str,#strLen1,#strLen2),
RIGHT(#str, #strlen2-#strlen1)
I would require that a colon or some other delimiter be between the message and the name.
Then you could just search for the index of that character and know that anything after it was the data you need...
Example with format changing over time:
CREATE TABLE #Temp (OrderInfo NVARCHAR(MAX))
INSERT INTO #Temp VALUES ('Order was assigned to :Smith,Mary')
INSERT INTO #Temp VALUES ('Order was assigned to :Holmes,Larry')
INSERT INTO #Temp VALUES ('New Format over time :LootAt,Me')
SELECT SUBSTRING(OrderInfo, CHARINDEX(':',OrderInfo)+1, LEN(OrderInfo))
FROM #Temp
DROP TABLE #Temp