Reverse substring - sql

I am trying to extract some characters from a string.
For Example in (316409953_ND_02142022_000001.pdf) I need the characters after the last underscore _ and before the "."
Answer: 000001
#test = 316409953_ND_02142022_000001.pdf
I have tried:
REVERSE(SUBSTRING(REVERSE(test),CHARINDEX('.',REVERSE(test))+1,CHARINDEX('_',REVERSE(test)+1)))
I need help with the last part of substring. First error I am getting is "Conversion failed when converting the varchar value 'fdp.100000_22024120_DN_359904613' to data type int."
Secondly I need it to pick only after the last "_"
Please guide or let me know if there's another way to do this.

This looks like SQL Server.
On that assumption, and using the single example value, you can try the follolwing:
declare #test varchar(50) = '316409953_ND_02142022_000001.pdf'
select #test OriginalValue,
ParseName(Right(#test, CharIndex('_',Reverse(#test))-1),2) ExtractedValue;

it isn't pretty but it does the job ;P
declare #str varchar(200) = '316409953_ND_02142022_000001.pdf'
declare #tempStr varchar(200)= (select SUBSTRING(#str,LEN(#str) + 2 - CHARINDEX('_',REVERSE(#str)),LEN(#str)))
set #tempStr = SUBSTRING(#tempStr,1,CHARINDEX('.',#tempStr) - 1)
select #tempStr

Related

Remove characters before and after string SQL

I would like to remove all characters before and after a string in the select statement.
In the example below I would like to remove everything before and including /Supply> and after and including >/
Note the remaining part will be a fixed number of characters.
Any help would be much appreciated
Eg.
abs/Supply>hhfhjgglldppprrr>/llllllldsfsjhfhhhfdhudfhfhdhdfhfsd
Would become:
hhfhjgglldppprrr
If your input always has exactly two instances of ">" you could use PARSENAME.
declare #SomeValue varchar(100) = 'abs/Supply>hhfhjgglldppprrr>/llllllldsfsjhfhhhfdhudfhfhdhdfhfsd'
select PARSENAME(replace(#SomeValue, '>', '.'), 2)
This will not work correctly if your data also contains any periods (.). We can deal with that if needed with a couple of replace statements. Still very simple and easy to maintain with the same caveat of exactly 2 >.
declare #SomeOtherValue varchar(100) = 'abs/Supply>hhfhjgg.lldppprrr>/llllllldsfsjhfhhhfdhudfhfhdhdfhfsd'
select replace(PARSENAME(replace(replace(#SomeOtherValue, '.', '~!##'), '>', '.'), 2), '~!##', '.')
You can use PATINDEX() to identify the position of the patterns you are looking for (/Supply> and >/) then remove them based on the length of the string:
SELECT LEFT(RIGHT(col,LEN(col) - PATINDEX('%/Supply>%',col) -7), PATINDEX('%>/%', RIGHT(col,LEN(col) - PATINDEX('%Supply>%',col) -7))-1)
Simply replace col in the above with your column name.
Example below with test string abs/Supply>keep>/remove
First remove everything before and including /Supply>:
SELECT RIGHT('abs/Supply>keep>/remove',LEN('abs/Supply>keep>/remove') - PATINDEX('%/Supply>%','abs/Supply>keep>/remove') -7)
This will give keep>/remove
Then remove everything after and including >/:
SELECT LEFT('keep>/remove',PATINDEX('%>/%','keep>/remove') - 1)
This will give keep, the part of the string you want.
Here is the combined version, same as above, just includes the test string instead of col so you can run it easily:
SELECT LEFT(RIGHT('abs/Supply>keep>/remove',LEN('abs/Supply>keep>/remove') - PATINDEX('%/Supply>%','abs/Supply>keep>/remove') -7), PATINDEX('%>/%', RIGHT('abs/Supply>keep>/remove',LEN('abs/Supply>keep>/remove') - PATINDEX('%/Supply>%','abs/Supply>keep>/remove') -7))-1)
This will give keep. You can also replace the string above with the one in your question, I just used a different test string because it is shorter and makes the code more readable.
try this:
DECLARE #inputStr VARCHAR(max)= 'abs/Supply>hhfhjgglldppprrr>/llllllldsfsjhfhhhfdhudfhfhdhdfhfsd'
DECLARE #startString VARCHAR(100)='/Supply>'
DECLARE #EndString VARCHAR(100)='>/'
DECLARE #LenStartString INT = LEN(#startString)
DECLARe #TempInputString VARCHAR(max)='';
DECLARE #StartIndex INT
DECLARE #EndIndex INT
SELECT #StartIndex = CHARINDEX(#startString,#inputStr)+#LenStartString
SELECT #TempInputString = STUFF(#inputStr, 1, #StartIndex, '')
SELECT SUBSTRING(#TempInputString,0,CHARINDEX(#EndString,#TempInputString))
In Single Line
DECLARE #inputStr VARCHAR(max)= 'abs/Supply>hhfhjgglldppprrr>/llllllldsfsjhfhhhfdhudfhfhdhdfhfsd'
DECLARE #startString VARCHAR(100)='/Supply>'
DECLARE #EndString VARCHAR(100)='>/'
SELECT SUBSTRING(STUFF(#inputStr, 1, CHARINDEX(#startString,#inputStr)+LEN(#startString), ''),0,CHARINDEX(#EndString,STUFF(#inputStr, 1,CHARINDEX(#startString,#inputStr)+LEN(#startString), '')))

Extract substring from string if certain characters exists SQL

I have a string:
DECLARE #UserComment AS VARCHAR(1000) = 'bjones marked inspection on system UP for site COL01545 as Refused to COD won''t pay upfront :Routeid: 12 :Inspectionid: 55274'
Is there a way for me to extract everything from the string after 'Inspectionid: ' leaving me just the InspectionID to save into a variable?
Your example doesn't quite work correctly. You defined your variable as varchar(100) but there are more characters in your string than that.
This should work based on your sample data.
DECLARE #UserComment AS VARCHAR(1000) = 'bjones marked inspection on system UP for site COL01545 as Refused to COD won''t pay upfront :Routeid: 12 :Inspectionid: 55274'
select right(#UserComment, case when charindex('Inspectionid: ', #UserComment, 0) > 0 then len(#UserComment) - charindex('Inspectionid: ', #UserComment, 0) - 13 else len(#UserComment) end)
I would do this as:
select stuff(#UserComment, 1, charindex(':Inspectionid: ', #UserComment) + 14, '')
This works even if the string is not found -- although it will return the whole string. To get an empty string in this case:
select stuff(#UserComment, 1, charindex(':Inspectionid: ', #UserComment + ':Inspectionid: ') + 14, '')
Firstly, let me say that your #UserComment variable is not long enough to contain the text you're putting into it. Increase the size of that first.
The SQL below will extract the value:
DECLARE #UserComment AS VARCHAR(1000); SET #UserComment = 'bjones marked inspection on system UP for site COL01545 as Refused to COD won''t pay upfront :Routeid: 12 :Inspectionid: 55274'
DECLARE #pos int
DECLARE #InspectionId int
DECLARE #IdToFind varchar(100)
SET #IdToFind = 'Inspectionid: '
SET #pos = CHARINDEX(#IdToFind, #UserComment)
IF #pos > 0
BEGIN
SET #InspectionId = CAST(SUBSTRING(#UserComment, #pos+LEN(#IdToFind)+1, (LEN(#UserComment) - #pos) + 1) AS INT)
PRINT #InspectionId
END
You could make the above code into a SQL function if necessary.
If the Inspection ID is always 5 digits then the last argument for the Substring function (length) can be 5, i.e.
SELECT SUBSTRING(#UserComment,PATINDEX('%Inspectionid:%',#UserComment)+14,5)
If the Inspection ID varies (but is always at the end - which your question slightly implies), then the last argument can be derived by subtracting the position of 'InspectionID:' from the overall length of the string. Like this:
SELECT SUBSTRING(#UserComment,PATINDEX('%Inspectionid:%',#UserComment)+14,LEN(#usercomment)-(PATINDEX('%Inspectionid:%',#UserComment)+13))

Conversion error despite using CAST?

I have a cursor which fetches reference codes from a table and increments the code by one if it fits certain criteria. The reference is alphanumeric so it is declared as nvarchar.
To keep things simple, assume that #RefNo = 'v1', with the intention of changing this to v2:
DECLARE #versionNo INT
DECLARE #RefNo nvarchar(50)
DECLARE #NewVersionNo INT
DECLARE #NewRefNo nvarchar(50)
set #VersionNo = Right(#RefNo, 1)
set #NewVersionNo = #versionNo + 1
set #NewRefNo = Left(#RefNo, Len(#RefNo - 1)) + cast(#NewVersionNo as nvarchar)
print #NewRefNo
The final line fails with error Conversion failed when converting the nvarchar value 'v1' to data type int. To an extent I get why this is happening - the '+' operator can't handle nvarchar and int values at the same time - but I would have thought the cast to nvarchar on #NewVersionNo would have avoided that.
Also note that I am using 2008R2 so am unable to use the CONCAT function.
you have miss place closing bracket, change your code of line as below
set #NewRefNo = Left(#RefNo, Len(#RefNo) - 1) + cast(#NewVersionNo as nvarchar)
-----------^
If #RefNo='V1'
Output:

How can I find part of a string between two words?

I want to get a part of text from my field description
Could someone offer some advice?
The whole string is 'Version100][BuildNumber:666][SubBuild:000]' and the build number is what I want to single out (however the number may change).
I have tried SUBSTRING with CHARINDEX but I can't seem to figure it out.
I've been googling for about 30 minutes and I can't seem to work it out.
little long, but you could do this.
DECLARE #Description VARCHAR(MAX)= '[Version100][BuildNumber:666][SubBuild:000]'
SELECT LEFT(STUFF(#Description, 1, PATINDEX('%BuildNumber%', #Description) + 11, '' )
,PATINDEX('%]%', STUFF(#Description, 1, PATINDEX('%BuildNumber%', #Description) + 11, '' )) - 1)
You can try this:
SELECT SUBSTRING([description],CHARINDEX('BuildNumber:',[description])+12,
CHARINDEX(']',[description], CHARINDEX('BuildNumber:',[description]))
-(CHARINDEX('BuildNumber:',[description])+12))
FROM YOURTABLE
I haven't actually tested this (numeric offsets might be a bit off, but you can tweak them), but assuming the string formats are always the same, then the following should work, irrespective of the number of digits in the build number.
SELECT SUBSTRING(description,
CHARINDEX('BuildNumber', description) + 11, --The position after BuildNumber: (a)
CHARINDEX('][SubBuild', description) - 3 - CHARINDEX('BuildNumber', description) + 11)) --The distance from (a) to the square brackets before SubBuild
Hope this query can return your expected result with out hard-coding the build number count:
DECLARE #Description AS VARCHAR (500) = 'Version100][BuildNumber:6663211][SubBuild:000]';
DECLARE #BeforeString AS VARCHAR (100) = '[BuildNumber:';
DECLARE #BeforeStringPosition AS INT = CHARINDEX(#BeforeString, #Description);
SELECT SUBSTRING(#Description, #BeforeStringPosition + LEN(#BeforeString) , CHARINDEX('][SubBuild', #Description) - #BeforeStringPosition - LEN(#BeforeString));

Is there any simple way to format decimals in T-SQL?

I know it could be done trivially in a non-SQL environment [post-data processing, frontend, what have you], but that's not possible at the moment. Is there a way to take a decimal(5,2) and convert it to a varchar without the trailing zeroes/decimal points? For example:
declare #number decimal(5,2)
set #number = 123.00
select cast(#number as varchar) as FormattedNumber
And the result is '123.00'. Is there a (simple) way to get '123' instead? And likewise, instead of '123.30', '123.3'? Could do it by figuring out whether or not the hundredths/tenths places were 0 and manually trimming characters, but I wanted to know if there was a more elegant solution.
What about:
SELECT CAST(CAST(#number AS float) AS varchar(10))
However you may want to test this carefully with your raw data first.
This way is pretty simple:
DECLARE #Number DECIMAL(5,2)
SELECT #Number = 123.65
SELECT FormattedNumber = CAST(CAST(#Number AS DECIMAL(3,0)) AS VARCHAR(4))
Returns '124'.
The only thing to consider is whether you want to round up/down, or just strip the zeroes and decimal points without rounding; you'd cast the DECIMAL as an INT in the second case.
For controlled formatting of numbers in T-SQL you should use the FORMAT() function. For example:
DECLARE #number DECIMAL(9,2); SET #number = 1234567.12;
DECLARE #formatted VARCHAR(MAX); SET #formatted = FORMAT(#number, 'N0', 'en-AU');
PRINT #formatted;
The result will be:
1,234,567
The arguments to the FORMAT() function are:
FORMAT(value, format [, culture])
The value argument is your number. The format argument is a CLR type formatting string (in this example, I specified "normal number, zero precision"). The optional culture argument allows you to override the server culture setting to format the number as per a desired culture.
See also the MSDN ref page for FORMAT().
The Convert function may do what you want to do.
ms-help://MS.SQLCC.v9/MS.SQLSVR.v9.en/tsqlref9/html/a87d0850-c670-4720-9ad5-6f5a22343ea8.htm
Let me try this again....
CREATE FUNCTION saneDecimal(#input decimal(5,2)) returns varchar(10)
AS
BEGIN
DECLARE #output varchar(10)
SET #output = CAST(#input AS varchar(10))
DECLARE #trimmable table (trimval char(1))
INSERT #trimmable VALUES ('0')
INSERT #trimmable VALUES ('.')
WHILE EXISTS (SELECT * FROM #trimmable WHERE trimval = CAST(SUBSTRING(#output, LEN(#output), 1) AS char(1)))
SET #output = LEFT(#output, LEN(#output) - 1)
RETURN #output
END
GO
SELECT dbo.saneDecimal(1.00)
You could strip the trailing zeroes in a while loop:
declare #number decimal(5,2)
declare #str varchar(100)
set #number = 123.00
set #str = #number
while substring(#str,len(#str),1) in ('0','.',',')
set #str = substring(#str,1,len(#str)-1)
But as AdaTheDev commented, this is more easily done client-side.
Simple and elegant? Not so much...but that's T-SQL for you:
DECLARE #number decimal(5,2) = 123.00
DECLARE #formatted varchar(5) = CAST(#number as varchar)
SELECT
LEFT(
#formatted,
LEN(#formatted)
- PATINDEX('%[^0.]%', REVERSE(#formatted))
+ 1
)
Use the Format(value,format string,culture) function in SQL Server 2012+
If you have SQL Server 2012 or Greater you can use the format function like this:
select format(#number,'0') as FormattedNumber
Of course the format function will return an nvarchar, and not a varchar. You can cast to get a specific type.
Also, take a look at the T-SQL STR function in Books Online; this can be used for formatting floats and might work for your case. For some reason it doesn't come up in Google searches relating to this problem.