SQL Selecting a value between 2 special characters where more than one special character exists - sql

I have a simple query:
LEFT(ReportMasterID, CHARINDEX(':', ReportMasterID) - 1) AS cons
I need to work out a variation of the script above that will pull back only the value between 2 special chars where there are more than one set of special chars in the string.
Here is the format of the string I need to pull the value from:
BORMG01D:BORMG:111111:1251624:40200
Obviously the above select generates an error because there are more than one set of special chars - I just need this value:
BORMG
Can anyone help please?

Here is a simple XML approach
Example
Declare #YourTable table (ID int,ReportMasterID varchar(max))
Insert Into #YourTable values
(1,'BORMG01D:BORMG:111111:1251624:40200')
Select ID
,Pos2 = convert(xml,'<x>'+replace(ReportMasterID,':','</x><x>')+'</x>').value('/x[2]','varchar(100)')
From #YourTable
Returns
ID Pos2
1 BORMG

Related

sql extract rightmost number in string and increment

i have transaction codes like
"A0004", "1B2005","20CCCCCCC21"
I need to extract the rightmost number and increment the transaction code by one
"AA0004"----->"AA0005"
"1B2005"------->"1B2006"
"20CCCCCCCC21"------>"20CCCCCCCC22"
in SQL Server 2012.
unknown length of string
right(n?) always number
dealing with unsignificant number of string and number length is out of my league.
some logic is always missing.
LEFT(#a,2)+RIGHT('000'+CONVERT(NVARCHAR,CONVERT(INT,SUBSTRING( SUBSTRING(#a,2,4),2,3))+1)),3
First, I want to be clear about this: I totally agree with the comments to the question from a_horse_with_no_name and Jeroen Mostert.
You should be storing one data point per column, period.
Having said that, I do realize that a lot of times the database structure can't be changed - so here's one possible way to get that calculation for you.
First, create and populate sample table (Please save us this step in your future questions):
DECLARE #T AS TABLE
(
col varchar(100)
);
INSERT INTO #T (col) VALUES
('A0004'),
('1B2005'),
('1B2000'),
('1B00'),
('20CCCCCCC21');
(I've added a couple of strings as edge cases you didn't mention in the question)
Then, using a couple of cross apply to minimize code repetition, I came up with that:
SELECT col,
LEFT(col, LEN(col) - LastCharIndex + 1) +
REPLICATE('0', LEN(NumberString) - LEN(CAST(NumberString as int))) +
CAST((CAST(NumberString as int) + 1) as varchar(100)) As Result
FROM #T
CROSS APPLY
(
SELECT PATINDEX('%[^0-9]%', Reverse(col)) As LastCharIndex
) As Idx
CROSS APPLY
(
SELECT RIGHT(col, LastCharIndex - 1) As NumberString
) As NS
Results:
col Result
A0004 A0005
1B2005 1B2006
1B2000 1B2001
1B00 1B01
20CCCCCCC21 20CCCCCCC22
The LastCharIndex represents the index of the last non-digit char in the string.
The NumberString represents the number to increment, as a string (to preserve the leading zeroes if they exists).
From there, it's simply taking the left part of the string (that is, up until the number), and concatenate it to a newly calculated number string, using Replicate to pad the result of addition with the exact number of leading zeroes the original number string had.
Try This
DECLARE #test nvarchar(1000) ='"A0004", "1B2005","20CCCCCCC21"'
DECLARE #Temp AS TABLE (ID INT IDENTITY,Data nvarchar(1000))
INSERT INTO #Temp
SELECT #test
;WITH CTE
AS
(
SELECT Id,LTRIM(RTRIM((REPLACE(Split.a.value('.' ,' nvarchar(max)'),'"','')))) AS Data
,RIGHT(LTRIM(RTRIM((REPLACE(Split.a.value('.' ,' nvarchar(max)'),'"','')))),1)+1 AS ReqData
FROM
(
SELECT ID,
CAST ('<S>'+REPLACE(Data,',','</S><S>')+'</S>' AS XML) AS Data
FROM #Temp
) AS A
CROSS APPLY Data.nodes ('S') AS Split(a)
)
SELECT CONCAT('"'+Data+'"','-------->','"'+CONCAT(LEFT(Data,LEN(Data)-1),CAST(ReqData AS VARCHAR))+'"') AS ExpectedResult
FROM CTE
Result
ExpectedResult
-----------------
"A0004"-------->"A0005"
"1B2005"-------->"1B2006"
"20CCCCCCC21"-------->"20CCCCCCC22"
STUFF(#X
,LEN(#X)-CASE PATINDEX('%[A-Z]%',REVERSE(#X)) WHEN 0 THEN LEN(#X) ELSE PATINDEX('%[A-Z]%',REVERSE(#X))-1 END+1
,LEN(((RIGHT(#X,CASE PATINDEX('%[A-Z]%',REVERSE(#X)) WHEN 0 THEN LEN(#X) ELSE PATINDEX('%[A-Z]%',REVERSE(#X))-1 END)/#N)+1)#N)
,((RIGHT(#X,CASE PATINDEX('%[A-Z]%',REVERSE(#X)) WHEN 0 THEN LEN(#X) ELSE PATINDEX('%[A-Z]%',REVERSE(#X))-1 END)/#N)+1)#N)
works on number only strings
99 becomes 100
mod(#N) increments

get last _ position values in sql server

Hi I have one doubt in sql server .
how to get first position to right side specific character position.
table : empfiles
filename:
ab_re_uk_u_20101001
ax_by_us_19991001
abc_20181002
I want output like below:
filename
ab_re_uk_u
ax_by_us
abc
I tried like below :
select SUBSTRING(filename,1,CHARINDEX('2',filename) - 1) as filename from empfiles
above query is not given expected result please tell me how to write query to achive this task in sql server .
If last position has always numeric values then you can use patindex():
select *, substring(filename, 1, patindex('%[0-9]%', filename)-2) as NewFile
from empfiles e;
If you want to get characters after than _ to right sight of string then you can use combo to reverse() and substring()
select *,
reverse(substring(reverse(filename),charindex('_', reverse(filename))+1, len(filename)))
from empfiles e;
Another way is to use reverse in combination with STUFF.
create table f(filename nvarchar(100));
insert into f values
('ab_re_uk_u_20101001')
,('ax_by_us_19991001')
,('abc_20181002');
select
filename=reverse(stuff(reverse(filename),1,charindex('_',reverse(filename)),''))
from f
Try This
CREATE TABLE #DATA([FILENAME] NVARCHAR(100));
INSERT INTO #DATA VALUES
('ab_re_uk_u_20101001')
,('ax_by_us_19991001')
,('abc_20181002');
SELECT [filename],
SUBSTRING([filename],0,PATINDEX('%[0-9]%',[filename])-1) AS ExpectedResult
FROM #Data
Result
filename ExpectedResult
--------------------------------------
ab_re_uk_u_20101001 ab_re_uk_u
ax_by_us_19991001 ax_by_us
abc_20181002 abc
Well, obviously the last position value is a date, and the format is YYYYMMDD so its 8 characters, plus, added by underscore character, so that makes its 9 character.
Assumed by the above statement applied, the following logic of the query should work
SELECT SUBSTRING(ColumnText, 1, LEN(ColumnText) - 9)
Which means, only display characters from character position 1, to character position LEN - 9, which LEN is the length of characters, and 9 is the last 9 digit of number to be removed
Try with this ..
select [filename],SUBSTRING([filename],1,PATINDEX('%_[0-9]%',[filename])-1) from empfiles
Individual Select records
SELECT SUBSTRING('ab_re_uk_u_20101001',1,PATINDEX('%_[0-9]%','ab_re_uk_u_20101001')-1)
SELECT SUBSTRING('ax_by_us_19991001',1,PATINDEX('%_[0-9]%','ax_by_us_19991001')-1)
SELECT SUBSTRING('abc_20181002',1,PATINDEX('%_[0-9]%','abc_20181002')-1)

Remove ASCII Extended Characters 128 onwards (SQL)

Is there a simple way to remove extended ASCII characters in a varchar(max). I want to remove all ASCII characters from 128 onwards. eg - ù,ç,Ä
I have tried this solution and its not working, I think its because they are still valid ASCII characters?
How do I remove extended ASCII characters from a string in T-SQL?
Thanks
The linked solution is using a loop which is - if possible - something you should avoid.
My solution is completely inlineable, it's easy to create an UDF (or maybe even better: an inline TVF) from this.
The idea: Create a set of running numbers (here it's limited with the count of objects in sys.objects, but there are tons of example how to create a numbers tally on the fly). In the second CTE the strings are splitted to single characters. The final select comes back with the cleaned string.
DECLARE #tbl TABLE(ID INT IDENTITY, EvilString NVARCHAR(100));
INSERT INTO #tbl(EvilString) VALUES('ËËËËeeeeËËËË'),('ËaËËbËeeeeËËËcË');
WITH RunningNumbers AS
(
SELECT ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) AS Nmbr
FROM sys.objects
)
,SingleChars AS
(
SELECT tbl.ID,rn.Nmbr,SUBSTRING(tbl.EvilString,rn.Nmbr,1) AS Chr
FROM #tbl AS tbl
CROSS APPLY (SELECT TOP(LEN(tbl.EvilString)) Nmbr FROM RunningNumbers) AS rn
)
SELECT ID,EvilString
,(
SELECT '' + Chr
FROM SingleChars AS sc
WHERE sc.ID=tbl.ID AND ASCII(Chr)<128
ORDER BY sc.Nmbr
FOR XML PATH('')
) AS GoodString
FROM #tbl As tbl
The result
1 ËËËËeeeeËËËË eeee
2 ËaËËbËeeeeËËËcË abeeeec
Here is another answer from me where this approach is used to replace all special characters with secure characters to get plain latin

How to find repeating numbers in a column in SQL server . Eg 11111, 33333333, 5555555555,7777777 etc

I need to identify repeated numbers( Eg: 1111, 33333333, 5555555555,777777777 etc.) in a column.
How can I do this in sql server without having to hard code every scenario. The max length is 10 of the column. Any help is appreciated.
This will check if the column has all the same value in it.
SELECT *
FROM tablename
WHERE columnname = REPLICATE(LEFT(columnname,1),LEN(columnname))
As Nicholas Cary notes, if the column is numbers you'd need to cast as varchar first:
SELECT *
FROM tablename
WHERE CAST(columnname AS VARCHAR(10)) = REPLICATE(LEFT(CAST(columnname AS VARCHAR(10)),1),LEN(CAST(columnname AS VARCHAR(10))))
Riffing on #Dave.Gugg's excellent answer, here's another way, using patindex() to look for a character different than the first.
select *
from some_table t
where 0 = patindex( '[^' + left(t.some_column,1) + ']' , t.some_column )
Again, this only works for string types (char,varchar, etc.). Numeric types such as int will need to be converted first.

A SQL Problem. Check condition with in a comma seperated value

I have a vairable
DECLARE #AssignOn nvarchar(20)='0,2,5'
I want to check a condition like this
DECLARE #index int
SET DATEFIRST 7
SELECT #index=DATEPART(DW, GETDATE())-1
IF(CONVERT(nvarchar(2),#index) IN #AssignOn)
IN cannot be used here . Any other methods to do this INLINE
You can use CharIndex to find if you have a match. It returns a non zero value if the first string appears in the second.
IF(CHARINDEX(CONVERT(nvarchar(2),#index), #AssignOn) > 0)
The easiest way to do this is to search for the substring ',needle,' in the csv list string. However, this doesn't work correctly for the first and last elements. This can be overcome by concatenating a comma onto each side of the csv list string.
An example in SQL might be:
SELECT
CHARINDEX(','+ NEEDLE +',', ','+ HAYSTACK +',')
FROM table;
Or using LIKE:
SELECT *
FROM table
WHERE ','+ HAYSTACK +',' LIKE '%,'+ NEEDLE +',';
IF CHARINDEX(','+CONVERT(nvarchar(2),#index)+',', ','+#AssignOn+',') <> 0
As you actually define the values in the code you could instead;
DECLARE #AssignOn TABLE (value int)
INSERT #AssignOn VALUES (0),(2),(5)
... #index IN (SELECT value FROM #AssignOn)