Get everything before a certain character in SQL - sql

I got the following entries in my database:
E01234-1-1
E01234444-1-800000000
I want to trim the entry so I get:
E01234-1
E01234444-1
So basically, I want everything before the second '-' regardless of the length
How can I solve it? Im using MS SQL SERVER 2012
I am using this but it only bring data from before first hyphen, not second hyphen
DECLARE #TABLE TABLE (STRING VARCHAR(100))
INSERT INTO #TABLE (STRING)
SELECT 'E01234-1-1'
UNION ALL SELECT 'E01234-1-200'
UNION ALL SELECT 'E01234-1-3000'
UNION ALL SELECT 'E01234-1-40000'
UNION ALL SELECT 'E01234-1-500000'
UNION ALL SELECT 'E01234-1-6000000'
UNION ALL SELECT 'E01234-1-70000000'
UNION ALL SELECT 'E01234444-1-800000000'
SELECT LEFT(STRING, CHARINDEX('-',STRING)-1) STRIPPED_STRING from #TABLE
RETURNS
E01234
E01234
E01234
E01234
E01234
E01234
E01234
E01234444

If you need the second -:
SELECT
LEFT(STRING, CHARINDEX('-', #test, CHARINDEX('-', #test) + 1) -1) STRIPPED_STRING
FROM #TABLE
Explanation: CHARINDEX will get you the index of the - - doing it twice (+ 1) specifies that the outter CHARINDEX should start at the spot after the first - in the string.
If you want to chop off everything after the last - instead (regardless of whether it's second or not):
SELECT
LEFT(STRING, LEN(STRING) - CHARINDEX('-', REVERSE(STRING))) STRIPPED_STRING
FROM #table
This time, you get the CHARINDEX of the last (reverse the string) -, and subtract that from the length of the whole string.

Try this:
DECLARE #STR NVARCHAR(MAX) = 'E01234444-1-800000000';
SELECT LEFT(#STR, CHARINDEX('-', #STR, CHARINDEX('-', #STR)) - 1)

If you are using MySQL use something like this:
SELECT SUBSTRING_INDEX(fieldname, '-', 2) FROM tablename

Related

Removing only the leading zero and not all zeros

the goal is to take the numbers in between 2 dashes and I was able to do that but the issue is that I need to remove the leading zero to the returned value. How can I incorporate the LTRIM function or other functions without removing all zeros?
Sample:
123-010-456
Results should be 10
SELECT[Phone],
REPLACE(SUBSTRING([Phone], CHARINDEX('-', [Phone]), CHARINDEX('-', [Phone])),'-','') AS substring
FROM [SalesLT].[Customer]
If your data pattern/format is fixed then below will help
SELECT RIGHT(PARSENAME(REPLACE('123-010-456','-','.'),2),2)
You can combine the following to one query, but for better understanding I break it down to 3 steps.
DECLARE #String nvarchar(20) = '123-010-456'
DECLARE #MiddlePart nvarchar(20)
DECLARE #FirstNonZero int
--Get the middle part
SET #MiddlePart = SUBSTRING(#String,
CHARINDEX('-',#String)+1, --Find the 1st dash
LEN(#String)-CHARINDEX('-',#String)-CHARINDEX('-',Reverse(#String)) --Find length between two dashes
)
--Get the First Non zero number
SET #FirstNonZero = (SELECT MIN(x)
FROM (SELECT CHARINDEX('1',#MiddlePart) as x WHERE CHARINDEX('1',#MiddlePart)>0
UNION
SELECT CHARINDEX('2',#MiddlePart) as x WHERE CHARINDEX('2',#MiddlePart)>0
UNION
SELECT CHARINDEX('3',#MiddlePart) as x WHERE CHARINDEX('3',#MiddlePart)>0
UNION
SELECT CHARINDEX('4',#MiddlePart) as x WHERE CHARINDEX('4',#MiddlePart)>0
UNION
SELECT CHARINDEX('5',#MiddlePart) as x WHERE CHARINDEX('5',#MiddlePart)>0
UNION
SELECT CHARINDEX('6',#MiddlePart) as x WHERE CHARINDEX('6',#MiddlePart)>0
UNION
SELECT CHARINDEX('7',#MiddlePart) as x WHERE CHARINDEX('7',#MiddlePart)>0
UNION
SELECT CHARINDEX('8',#MiddlePart) as x WHERE CHARINDEX('8',#MiddlePart)>0
UNION
SELECT CHARINDEX('9',#MiddlePart) as x WHERE CHARINDEX('9',#MiddlePart)>0
) a)
--Final
Select SUBSTRING(#MiddlePart,#FirstNonZero,LEN(#MiddlePart)-#FirstNonZero+1)
You could try to extract the middle part and convert it to int - this will remove all leading zeroes while keeping the trailing ones... if required, you can then convert it back to varchar. Following an example:
DECLARE #t TABLE(testval nvarchar(40))
INSERT INTO #t VALUES
('123-010-456')
,('1234-1-456789')
,('12-00010-4')
,('1-0007-4')
SELECT *
,SUBSTRING(testval, CHARINDEX('-', testval)+1, CHARINDEX('-', testval, CHARINDEX('-', testval)+1)-CHARINDEX('-', testval)-1)
,CAST(SUBSTRING(testval, CHARINDEX('-', testval)+1, CHARINDEX('-', testval, CHARINDEX('-', testval)+1)-CHARINDEX('-', testval)-1) AS INT)
FROM #t

SQL: select the last values before a space in a string

I have a set of strings like this:
CAP BCP0018 36
MFP ACZZ1BD 265
LZP FEI-12 3
I need to extract only the last values from the right and before the space, like:
36
265
3
how will the select statement look like? I tried using the below statement, but it did not work.
select CHARINDEX(myField, ' ', -1)
FROM myTable;
Perhaps the simplest method in SQL Server is:
select t.*, v.value
from t cross apply
(select top (1) value
from string_split(t.col, ' ')
where t.col like concat('% ', val)
) v;
This is perhaps not the most performant method. You probably would use:
select right(t.col, charindex(' ', reverse(t.col)) - 1)
Note: If there are no spaces, then to prevent an error:
select right(t.col, charindex(' ', reverse(t.col) + ' ') - 1)
Since you have mentioned CHARINDEX() in question, I am assuming you are using SQL Server.
Try below
declare #table table(col varchar(100))
insert into #table values('CAP BCP0018 36')
insert into #table values('MFP ACZZ1BD 265')
insert into #table values('LZP FE-12 3')
SELECT REVERSE(LEFT(REVERSE(col),CHARINDEX(' ',REVERSE(col)) - 1)) FROM #table
Functions used
CHARINDEX ( expressionToFind , expressionToSearch ) : returns position of FIRST occurence of an expression inside another expression.
LEFT ( character_expression , integer_expression ) : Returns the left part of a character string with the specified number of characters.
REVERSE ( string_expression ) : Returns the reverse order of a string value

How to pull out information from a long string of data

I have this data point:
455-U-202007302233,455-L-202007302233,422-U-202008011052,422-L-202008011052,857-U-202008041142,857-L-202008061215
Column: ,[t810str]
How would I be able to modify column [t810str] in order to pull out the last comma set before 857?
Desired Result = 422-L-202008011052
First you need to implement some kind of splitter that respects ordinal position (STRING_SPLIT does not). I'm therefore going to make use of DelimitedSplit8k_LEAD. Then you can split the value, and use LAG to get the prior value. Finally you can filter on where the item has a value LIKE '857%' but the previous does not:
WITH CTE AS(
SELECT DS.Item,
LAG(DS.Item) OVER (PARTITION BY YourColumn ORDER BY DS.itemNumber) AS PrevItem
FROM (VALUES('455-U-202007302233,455-L-202007302233,422-U-202008011052,422-L-202008011052,857-U-202008041142,857-L-202008061215'))V(YourColumn)
CROSS APPLY dbo.DelimitedSplit8K_LEAD(V.YourColumn,',') DS)
SELECT C.PrevItem
FROM CTE C
WHERE C.Item LIKE '857%'
AND C.PrevItem NOT LIKE '857%';
Based on your data and the assumption that items are 18 characters (your data do not indicate otherwise):
DECLARE #t AS NVARCHAR(255) = '455-U-202007302233,455-L-202007302233,422-U-202008011052,422-L-202008011052,857-U-202008041142,857-L-202008061215';
SELECT RIGHT(LEFT(#t,CHARINDEX(',857',#t)-1),18)
Using cross apply (which you can also rewrite using a CTE or a subquery for readability). This removes everything after first occurrence of 857 and then grabs the last set that's left. So even if you have multiple 857 and varying length of delimited strings, this should work
select *, right(remind , charindex (',' ,reverse(remind))-1)
from t t1
cross apply (select stuff(col, charindex(',857',col), len(col),'') as remind) t2
DEMO
Another solution use a recursive CTE
DECLARE #Var VARCHAR(200) = '455-U-202007302233,455-L-202007302233,422-U-202008011052,422-L-202008011052,857-U-202008041142,857-L-202008061215';
WITH CTE AS
(
SELECT 0 N, LEFT(#Var, CHARINDEX(',', #Var)-1) Part,
RIGHT(#Var, LEN(#Var) - CHARINDEX(',', #Var)) Remind
UNION ALL
SELECT N + 1,
LEFT(Remind, CHARINDEX(',', Remind) - 1),
RIGHT(Remind, LEN(Remind) - CHARINDEX(',', Remind))
FROM CTE
WHERE CHARINDEX(',', Remind) <> 0
)
SELECT TOP 1 Part
FROM CTE
WHERE LEFT(Remind, 3) = '857'
ORDER BY N;
Demo
Implemented with string functions (and assuming your data items can have variable length :-) it might look a bit confusing (therefore I'd prefer #Larnu's answer):
DECLARE #string VARCHAR(2000) = '455-U-202007302233,455-L-202007302233,422-U-202008011052,422-L-202008011052,857-U-202008041142,857-L-202008061215'
SELECT SUBSTRING(#string, CHARINDEX(',857',#string) - CHARINDEX(',', REVERSE( LEFT(#string, PATINDEX('%,857%',#string) - 1)) ) + 1, CHARINDEX(',', REVERSE( LEFT(#string, PATINDEX('%,857%',#string) - 1)))-1 )
Parts of the latter separated:
DECLARE #string VARCHAR(2000) = '455-U-202007302233,455-L-202007302233,422-U-202008011052,422-L-202008011052,857-U-202008041142,857-L-202008061215'SELECT CHARINDEX(',857',#string)
SELECT LEFT(#string, PATINDEX('%,857%',#string) - 1)
SELECT REVERSE( LEFT(#string, PATINDEX('%,857%',#string) - 1) )
SELECT CHARINDEX(',', REVERSE( LEFT(#string, PATINDEX('%,857%',#string) - 1)) )

How do I select a substring from two different patindex?

I have many different types of string, but they all follow the two same patterns:
ABC123-S-XYZ789
ABC123-P-XYZ789
QUESTION 1:
I know how I can extract the first part: ABC123
But how do I extract the second part??? XYZ789
QUESTION 2:
I can't tell beforehand if the string follows the -S- pattern or the -P- pattern, it can be different each time. Anyone who know how I can solve this?
Thanks! / Sophie
You can try following code:
SELECT CASE WHEN #a LIKE '%-S-%' THEN right(#a, CHARINDEX('-S-', #a)-1)
WHEN #a LIKE '%-P-%' THEN right(#a, CHARINDEX('-P-', #a)-1)
ELSE NULL END AS 'ColName'
FROM tablename
Is this what you need?
DECLARE #Input VARCHAR(100) = 'ABC123-S-XYZ789'
SELECT
FirstPart = SUBSTRING(
#Input,
1,
CHARINDEX('-', #Input) - 1),
SecondPart = SUBSTRING(
#Input,
LEN(#Input) - CHARINDEX('-', REVERSE(#Input)) + 2,
100),
Pattern = CASE
WHEN #Input LIKE '%-S-%' THEN 'S'
WHEN #Input LIKE '%-P-%' THEN 'P' END
You can use parsename() if the string has always this kind of parts such as ABC123-S-XYZ789
select col, parsename(replace(col, '-', '.'), 1)
However, the parsename() requires the SQL Server+12 if not then you can use reverse()
select col, reverse(left(reverse(col), charindex('-', reverse(col))-1))
If you're using SQL Server 2016 or newer, you can use STRING_SPLIT
CREATE TABLE #temp (string VARCHAR(100));
INSERT #temp VALUES ('ABC123-S-XYZ789'),('ABC123-P-XYZ789');
SELECT *, ROW_NUMBER() OVER (PARTITION BY string ORDER BY string)
FROM #temp t
CROSS APPLY STRING_SPLIT(t.string, '-');
I can't tell beforehand if the string folllows the -S- pattern or the -P- pattern
You can then use a CTE to get a specific part of the string:
WITH cte AS (
SELECT *, ROW_NUMBER() OVER (PARTITION BY string ORDER BY string) rn
FROM #temp t
CROSS APPLY STRING_SPLIT(t.string, '-')
)
SELECT * FROM cte WHERE rn = 2

I want to remove part of string from a string

Thank you in advance.
I want to remove string after . including ., but length is variable and string can be of any length.
1)Example:
Input:- SCC0204.X and FRK0005.X and RF0023.X and ADF1010.A and HGT9010.V
Output: SCC0204 and FRK0005 and RF0023 and ADF1010.A and HGT9010.V
I tried using the charindex but as the length keeps on changing i wasn't able to do it. I want to trim the values with ending with only X
Any help will be greatly appreciated.
Assuming there is only one dot
UPDATE TABLE
SET column_name = left(column_name, charindex('.', column_name) - 1)
For SELECT
select left(column_name, charindex('.', column_name) - 1) AS col
from your_table
Hope this helps. The code only trims the string when the value has a decimal "." in it and if that value is equal to .X
;WITH cte_TestData(Code) AS
(
SELECT 'SCC0204.X' UNION ALL
SELECT 'FRK0005.X' UNION ALL
SELECT 'RF0023.X' UNION ALL
SELECT 'ADF1010.A' UNION ALL
SELECT 'HGT9010.V' UNION ALL
SELECT 'SCC0204' UNION ALL
SELECT 'FRK0005'
)
SELECT CASE
WHEN CHARINDEX('.', Code) > 0 AND RIGHT(Code,2) = '.X'
THEN SUBSTRING(Code, 1, CHARINDEX('.', Code) - 1)
ELSE Code
END
FROM cte_TestData
If the criteria is only to replace remove .X then probably this should also work
;WITH cte_TestData(Code) AS
(
SELECT 'SCC0204.X' UNION ALL
SELECT 'FRK0005.X' UNION ALL
SELECT 'RF0023.X' UNION ALL
SELECT 'ADF1010.A' UNION ALL
SELECT 'HGT9010.V' UNION ALL
SELECT 'SCC0204' UNION ALL
SELECT 'FRK0005'
)
SELECT REPLACE (Code,'.X','')
FROM cte_TestData
Use LEFT String function :
DECLARE #String VARCHAR(100) = 'SCC0204.XXXXX'
SELECT LEFT(#String,CHARINDEX('.', #String) - 1)
I think your best bet here is to create a function that parses the string and uses regex. I hope this old post helps:
Perform regex (replace) in an SQL query
However, if the value you need to trim is constantly ".X", then you should use
select replace(string, '.x', '')
Please check the below code. I think this will help you.
DECLARE #String VARCHAR(100) = 'SCC0204.X'
IF (SELECT RIGHT(#String,2)) ='.X'
SELECT LEFT(#String,CHARINDEX('.', #String) - 1)
ELSE
SELECT #String
Update: I just missed one of the comments where the OP clarifies the requirement. What I put together below is how you would deal with a requirement to remove everything after the first dot on strings ending with X. I leave this here for reference.
;WITH cte_TestData(Code) AS
(
SELECT 'SCC0204.X' UNION ALL -- ends with '.X'
SELECT 'FRK.000.X' UNION ALL -- ends with '.X', contains multiple dots
SELECT 'RF0023.AX' UNION ALL -- ends with '.AX'
SELECT 'ADF1010.A' UNION ALL -- ends with '.A'
SELECT 'HGT9010.V' UNION ALL -- ends with '.V'
SELECT 'SCC0204.XF' UNION ALL -- ends with '.XF'
SELECT 'FRK0005' UNION ALL -- totally clean
SELECT 'ABCX' -- ends with 'X', not dots
)
SELECT
orig_string = code,
newstring =
SUBSTRING
(
code, 1,
CASE
WHEN code LIKE '%X'
THEN ISNULL(NULLIF(CHARINDEX('.',code)-1, -1), LEN(code))
ELSE LEN(code)
END
)
FROM cte_TestData;
FYI - SQL Server 2012+ you could simplify this code like this:
SELECT
orig_string = code,
newstring =
SUBSTRING(code, 1,IIF(code LIKE '%X', ISNULL(NULLIF(CHARINDEX('.',code)-1, -1), LEN(code)), LEN(code)))
FROM cte_TestData;
With SUBSTRING you can achieve your requirements by below code.
SELECT SUBSTRING(column_name, 0, CHARINDEX('.', column_name)) AS col
FROM your_table
If you want to remove fixed .X from string you can also use REPLACE function.
SELECT REPLACE(column_name, '.X', '') AS col