Splitting of varchar column using the special character - sql-server

I have a column which values will be
1_987123
12_987654
Here, I need to separate only the first letter that is '1' and '12' in the column values. I have tried substring and charindex to find the value. The syntax I have used is:
substring(Columnname,1,charindex('_',Columnname,1)-1).
This works to find for the column which have values. But in my case we have blank values in the column. In that case the above syntax is giving error. Tried the scenarios like coalesce and its not accepting as the column data type is varchar.
Can you please suggest me some other option?

You need to use a CASE expression to handle values without '_':
WITH Tbl(col) AS(
SELECT '1_987123' UNION ALL
SELECT '12_987654' UNION ALL
SELECT '12'
)
SELECT
CASE
WHEN CHARINDEX('_', col) > 0 THEN LEFT(col, CHARINDEX('_', col)-1)
ELSE col
END
FROM Tbl

or you can cheat a bit by apending the underscore at the back
SELECT LEFT (col, CHARINDEX('_', col + '_') - 1)

You can try like this, It supports null values, values without underscore and empty strings values in your columns.
SELECT CASE
WHEN charindex('_', COL) > 0
THEN substring(col, 1, charindex('_', COL) - 1)
ELSE col
END
FROM (
VALUES ('1_987123')
,('12_987654')
,('12')
,(NULL)
,('')
) T(COL)
Use filter like this,
SELECT CASE
WHEN charindex('_', COL) > 0
THEN substring(col, 1, charindex('_', COL) - 1)
ELSE col
END
FROM (
VALUES ('1_987123')
,('12_987654')
,('12')
,(NULL)
,('')
,('3_545')
,('3')
) T(COL)
where col like '3%'

There is a trick you can use, start at position 0 instead of position 1 and do not subtract 1. This will return empty string when there is no underscore.
SELECT
SUBSTRING(Columnname,0,charindex('_',Columnname,1))
FROM (values('1_987123'),('7123'),('12_987654')) x(columnname)
Result:
1
12

Related

SQL string before and after certain characters

SELECT NAME
FROM SERVERS
returns:
SDACR.hello.com
SDACR
SDACR\AIR
SDACR.hello.com\WATER
I need the SELECT query for below result:
SDACR
SDACR
SDACR\AIR
SDACR\WATER
Kindly help ! I tried using LEFT and RIGHT functions as below, but not able to get combined output correctly:
SELECT
LEFT(Name, CHARINDEX('.', Name) - 1)
FROM
SERVERS
SELECT
RIGHT(Name, LEN(Name) - CHARINDEX('\', Name))
FROM
SERVERS
It looks like you're just trying to REPLACE a substring of characters in your column. You should try this:
SELECT REPLACE(Name,'.hello.com','') AS ReplacementName
FROM SERVERS
In tsql, you can concatenate values with CONCAT(), or you can simply add strings together with +.
SELECT LEFT(Name, CHARINDEX('.',Name)-1) + RIGHT(Name,LEN(Name)-CHARINDEX('\',Name)) from SERVERS
Also, be careful with doing arithmetic with CHARINDEX(). A value without a '.' or a '\' will return a NULL and you will get an error.
You can use LEFT for this to select everything up to the first period (dot) and add on everything after the last \
declare #servers table ([NAME] varchar(64))
insert into #servers
values
('SDACR.hello.com '),
('SDACR'),
('SDACR\AIR'),
('SDACR.hello.com\WATER')
select
left([NAME],case when charindex('.',[NAME]) = 0 then len([NAME]) else charindex('.',[NAME]) -1 end) +
case when charindex('\',left([NAME],case when charindex('.',[NAME]) = 0 then len([NAME]) else charindex('.',[NAME]) -1 end)) = 0 then right([NAME],charindex('\',reverse([NAME]))) else '' end
from #servers
Throwing my hat in.... Showing how to use Values and APPLY for cleaner code.
-- sample data in an easily consumable format
declare #yourdata table (txt varchar(100));
insert #yourdata values
('SDACR.hello.com'),
('SDACR'),
('SDACR\AIR'),
('SDACR.hello.com\WATER');
-- solution
select
txt,
newTxt =
case
when loc.dot = 0 then txt
when loc.dot > 0 and loc.slash = 0 then substring(txt, 1, loc.dot-1)
else substring(txt, 1, loc.dot-1) + substring(txt, loc.slash, 100)
end
from #yourdata
cross apply (values (charindex('.',txt), (charindex('\',txt)))) loc(dot,slash);
Results
txt newTxt
------------------------------ --------------------
SDACR.hello.com SDACR
SDACR SDACR
SDACR\AIR SDACR\AIR
SDACR.hello.com\WATER SDACR\WATER

Return 1.23 from 1.2.3 in SQL?

I want to get the value 1.23 from 1.2.3.Similar, I also get the value 1.2.3...x from 1.2.3...x .How can I do this in SQL?
After I get number from string in this topic: How to get number from String sql
Now, this value is 1.2.3. When i cast, sql notice an error: "Error converting data type nvarchar to float" And i want to return the value 1.23 from 1.2.3
you can also use a combination of STUFF and REPLACE and CHARINDEX to achieve what you require. The solution saves the first location of . , replaces all the other decimal points and then stuffs it back in. Something like this
;WITH CTE AS
(
SELECT '1.23' as CharCol
UNION ALL SELECT '6.7.1.'
UNION ALL SELECT '4.2.3'
UNION ALL SELECT '1.46'
UNION ALL SELECT '5.43'
UNION ALL SELECT '90'
)
SELECT
CASE WHEN CHARINDEX('.',CharCol) = 0
THEN CharCol
ELSE STUFF(REPLACE(CharCol,'.',''),CHARINDEX('.',CharCol),0,'.')
END
FROM CTE;
You can use an ugly combination of SUBSTRING, REPLACE and PATINDEX. Something like
SELECT
SUBSTRING(a, 1, PATINDEX('%.%', a) - 1) AS pre
,REPLACE(SUBSTRING(a, PATINDEX('%.%', a), LEN(a)), '.', '') AS post
,SUBSTRING(a, 1, PATINDEX('%.%', a) - 1) + '.' + REPLACE(SUBSTRING(a, PATINDEX('%.%', a), LEN(a)), '.', '') AS result
FROM (
SELECT
'1.2.3' AS a
) I
The pre and post columns are the two halves, appended them with a '.' in the result column.
The number before the first '.' will remain before, while any numbers after the the first '.' will be put together after the '.'
e.g.
432.546.3.132.6 = 432.54631326

SQL: Filter on Alpha and numeric on column of Type TEXT

I've got a column of type Text. In the column are numeric values such as4, 8, 3.2, etc... and also values such as 'Negative', 'Positive', '27A', '2pos 1neg'.
The user needs to be able to say: "Give me all the values between 10 and 30, and also the values that are 'Negative'. The WHERE clause would need to do something along the lines of:
WHERE Tbl.Col > 10
AND Tbl.Col < 30
AND Tbl.Col = 'Negative'
This is problematic for obvious reasons. I've tried using the ISNUMERIC function to alleviate the issue but can't seem to get exactly what i need. I can either get all the alpha values in the column, or all the numeric values in the column as floats but cant seem to filter on both at the same time. To grab all the Numeric values I've been using this:
SELECT Num.Val FROM
(SELECT Val = CASE ISNUMERIC(CAST(TBL.COL AS VARCHAR)) WHEN 1
THEN CAST(CAST(TBL.COL AS VARCHAR) AS FLOAT) ELSE NULL END
FROM Table TBL
WHERE TBL.COL IS NOT NULL ) as Num
WHERE Num.val IS NOT NULL
AND Num.val > 10
If I understand the issue correctly something like this should get you close.
with MyNumbers as
(
select t.Col
from Tbl t
--where ISNUMERIC(t.Col) = 1
where t.Col NOT LIKE '%[^0-9.]%'
)
, MyAlpha as
(
select t.Col
from Tbl t
where ISNUMERIC(t.Col) = 0
)
select Col
from MyNumbers
where Col > 10
and Col < 30
union all
select Col
from MyAlpha
where ColorMatch = ' Negative'
First I would go slap the person who designed the table (hopefully it isn't you) :>
Go to here and get the split table function. I would then convert the text column (like you have in example above) into varchar(max) and supply it as the parameter to the split function. Then you could select from the table results of the split function using the user supplied parameters.
I have found the answer to my problem:
SELECT
al_Value = Table.Column
FROM Table
WHERE (
ISNUMERIC(CAST(Table.Column AS VARCHAR)) = 1 AND
CONVERT(FLOAT, CAST(Table.Column AS VARCHAR)) > 1.0 AND
CONVERT(FLOAT, CAST(Table.Column AS VARCHAR)) < 10.0
)
OR (
CAST(Table.Column AS VARCHAR) IN ('negative', 'no bueno')
)
This will return one column named 'al_Value' that filters on Table.Column (which is of Datatype TEXT) and apply the filters in the WHERE clause above.
Thanks everyone for trying to help me with this issue.

How to truncate string using SQL server

i have large string in SQL Server. I want to truncate that string to 10 or 15 character
Original string
this is test string. this is test string. this is test string. this is test string.
Desired string
this is test string. this is ......
If you only want to return a few characters of your long string, you can use:
select
left(col, 15) + '...' col
from yourtable
See SQL Fiddle with Demo.
This will return the first 15 characters of the string and then concatenates the ... to the end of it.
If you want to to make sure than strings less than 15 do not get the ... then you can use:
select
case
when len(col)>15
then left(col, 15) + '...'
else col end col
from yourtable
See SQL Fiddle with Demo
You can use
LEFT(column, length)
or
SUBSTRING(column, start index, length)
You can also use the Cast() operation :
Declare #name varchar(100);
set #name='....';
Select Cast(#name as varchar(10)) as new_name
I think the answers here are great, but I would like to add a scenario.
Several times I've wanted to take a certain amount of characters off the front of a string, without worrying about it's length. There are several ways of doing this with RIGHT() and SUBSTRING(), but they all need to know the length of the string which can sometimes slow things down.
I've use the STUFF() function instead:
SET #Result = STUFF(#Result, 1, #LengthToRemove, '')
This replaces the length of unneeded string with an empty string.
You could also use the below, the iif avoids the case statement and only adds ellipses when required (only good in SQL Server 2012 and later) and the case statement is more ANSI compliant (but more verbose)
SELECT
col, LEN(col),
col2, LEN(col2),
col3, LEN(col3) FROM (
SELECT
col,
LEFT(x.col, 15) + (IIF(len(x.col) > 15, '...', '')) AS col2,
LEFT(x.col, 15) + (CASE WHEN len(x.col) > 15 THEN '...' ELSE '' END) AS col3
from (
select 'this is a long string. One that is longer than 15 characters' as col
UNION
SELECT 'short string' AS col
UNION
SELECT 'string==15 char' AS col
UNION
SELECT NULL AS col
UNION
SELECT '' AS col
) x
) y
CASE
WHEN col IS NULL
THEN ''
ELSE SUBSTRING(col,1,15)+ '...'
END AS Col

SQL Server converting a variable varchar field to money/decimal/something with decimal places

I'm looking for an elegant way to convert a field of type varchar, with variable data in it, to a data type which can be used for mathematical operations sample data from the field
(excluding quotes)
''
'abc'
'23'
'23.2'
The method should work for all, and for the first & second values should return 0, and not throw an SQL Server error..
Try this:
SELECT CASE WHEN IsNumeric(YourColumn) = 0 THEN
0
ELSE
CAST(YourColumn AS decimal(18, 2))
END
You have to adjust the destination data type, I have chosen decimal(18, 2) for demonstration.
I know this is a long-dead thread, but I recently stumbled upon it from a Google search and had a thought. It is less elegant than a CASE statement, but it is an alternative.
SELECT
COALESCE(CAST(NULLIF(ISNUMERIC(LEFT(MyColumn, PATINDEX('% %', MyColumn + ' ') - 1)), 1) AS MONEY), LEFT(MyColumn, PATINDEX('% %', MyColumn + ' ') - 1))
FROM
myTable
or you could do:
Select COALESCE(CAST(NULLIF(ISNUMERIC(MyColumn), 1) AS MONEY), MyColumn)
FROM
myTable
The top version would see "2 5" as just 2, the bottom one would see it as a text field.
SELECT CASE IsNumeric(mycol) WHEN 1 THEN CAST(mycol AS FLOAT) ELSE 0 END
FROM mytable
If you'd like to convert it, you should use UPDATE instead of SELECT
UPDATE Table
SET Col1 = CAST(Col1 As Decimal(18,2))
COALESCE is a great option for this: Find more information here. It evaluates the arguments in order and returns the current value of the first expression that initially does not evaluate to NULL.
ISNUMERIC returns 0 or 1 depending on if the value being evaluated could be considered one of the SQL 'number' or 'numeric' types. e.g. int, bigint, money..
NULLIF essentially finds the value you specify and if it matches it replaces it with a NULL value.
CAST Simply changes a data type to another in this example to MONEY
As you can see, if you break the below down using this information its quite an elegant solution I think?
COALESCE(CAST(NULLIF(ISNUMERIC(COL1), 1) AS MONEY), COL1)

Resources