I have a query that in SQL Server that returns data like this:
1234-A
2345-BB
3456-C
5678-CC
4567-AA
6789-B
01234-A
26857-ZZ
This is what I need it display:
A
B
C
C
A
B
A
Z
I need to get the first letter behind the '-'. How do I get this to display?
Try this:
DECLARE #MyTable TABLE (MyCol VARCHAR(255));
INSERT #MyTable (MyCol)
VALUES ('1234-A'),('2345-BB'),('3456-C'),('5678-CC'),
('4567-AA'),('6789-B'),('01234-A'),('26857-ZZ');
SELECT SUBSTRING(MyCol, CHARINDEX('-', MyCol, 1) + 1, 1)
FROM #MyTable;
CHARINDEX finds where the '-' in the column value is.
SUBSTRING starts at that index + 1 and returns, in this case, 1 character.
You can use substr In conjunction with instr to get the output
Related
I have column and need to extract number between 2 pipes |, example data inside is AAA|12345678|#RRR. I need to get this number 12345678.
my code is:
SELECT SUBSTRING(column_name,CHARINDEX('|',column_name) + 1, CHARINDEX('|',column_name) - CHARINDEX('|',column_name) - 1)
FROM [name].[name].[table_name]
Using your own code:
SELECT SUBSTRING(column_name,CHARINDEX('|',column_name) + 1,
CHARINDEX('|',column_name) - CHARINDEX('|',column_name) - 1)
FROM [name].[name].[table_name]
The second part of substring is not correct. It should be:
SELECT SUBSTRING(column_name,CHARINDEX('|',column_name) + 1,
CHARINDEX('|',column_name, CHARINDEX('|',column_name)))
FROM [name].[name].[table_name]
The nested CHARINDEX will look for the position of the second pipe. and the SUBSTRING will start from the first pipe and continue to the second
Assuming the 2nd position, you can use a little XML or ParseName()
XML Example
Declare #YourTable table (ID int,column_name varchar(max))
Insert Into #YourTable values
(1,'AAA|12345678|#RRR')
Select ID
,SomeValue = Cast('<x>' + replace(column_name,'|','</x><x>')+'</x>' as xml).value('/x[2]','varchar(max)')
From #YourTable
ParseName() Example
Select ID
,SomeValue = parsename(replace(column_name,'|','.'),2)
From #YourTable
Both would Return
ID SomeValue
1 12345678
String extraction is generally tricky in SQL Server. But if you only have one numeric value and are looking for it, then the code isn't that bad:
select patindex('%[0-9]|%', str),
substring(str, patindex('%|[0-9]%', str), patindex('%[0-9]|%', str) - patindex('%|[0-9]%', str) + 1)
from (values ('AAA|12345678|#RRR')) v(str)
I would use PARSENAME() :
select parsename(replace(str, '|', '.'), 2)
from ( values ('AAA|12345678|#RRR')
) v(str);
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)
I have few columns in my old database that have values where number and letters are combined together. This is something that I have to clean and import in the new table. The most of the values that need to be converted look like this:
40M or 85M or NR or 5NR ...
Since there wasn't any validation what user can enter in the old system there still can be values like: 40A or 3R and so on. I want to import only numeric values in my new table. So if there is any letters in the value I want to trim them. What is the best way to do that in SQL Server? I have tried this:
CASE WHEN CHARINDEX('M',hs_ptr1) <> 0 THEN 1 ELSE 0 END AS hs_ptr1
but this will only identify if one letter is in the value. If anyone can help please let me know. Thanks!
you can use patindex to search for the pattern. Try this code:
Code:
CREATE TABLE #temp
(
TXT NVARCHAR(50)
)
INSERT INTO #temp (TXT)
VALUES
('40M'),
('85M'),
('NR'),
('5NR')
SELECT LEFT(subsrt, PATINDEX('%[^0-9]%', subsrt + 't') - 1)
FROM (
SELECT subsrt = SUBSTRING(TXT, pos, LEN(TXT))
FROM (
SELECT TXT, pos = PATINDEX('%[0-9]%', TXT)
FROM #temp
) d
) t
DROP TABLE #temp
Here's a way without a function....
declare #table table (c varchar(256))
insert into #table
values
('40M'),
('30'),
('5NR'),
('3(-4_')
select
replace(LEFT(SUBSTRING(replace(replace(replace(replace(replace(c,'(',''),')',''),'-',''),' ',''),',',''), PATINDEX('%[0-9.-]%', replace(replace(replace(replace(replace(c,'(',''),')',''),'-',''),' ',''),',','')), 8000),
PATINDEX('%[^0-9.-]%', SUBSTRING(replace(replace(replace(replace(replace(c,'(',''),')',''),'-',''),' ',''),',',''), PATINDEX('%[0-9.-]%', replace(replace(replace(replace(replace(c,'(',''),')',''),'-',''),' ',''),',','')), 8000) + 'X') -1),'.','')
from #table
You go with the PATINDEX function and search for a character that is not a digit. If such an index exists, then grab everything to the left of it. Something like that:
SELECT LEFT(your_field_name, PATINDEX("%[^0-9]%", your_field_name) - 1)
FROM your_table_name
UPDATE
Well, you need to take care of any edge cases. E.g. if there isn't a non-digit data the function will return 0, thus the calculation yields -1, which, indeed, is an invalid length.
I would suggest you to leverage a Common Table Expression to calculate the index of the non-digit data and then construct an IIF expression to select the correct char data. E.g.
WITH cte AS
(
SELECT *, PATINDEX("%[^0-9]%", your_field_name) AS NumLength
FROM your_table_name
)
SELECT any_other_field, IIF(NumLength = 0,
your_field_name,
LEFT(your_field_name, PATINDEX("%[^0-9]%", your_field_name) - 1)
)
FROM cte
I am trying to formulate a query that will allow me to find all records from a single column with 3 hyphens. An example of a record would be like XXXX-RP-XXXAS1-P.
I need to be able to sort through 1000s of records with either 2 or 3 hyphens.
You can REPLACE the hyphens in the string with an empty string and compute the difference of the length of original string and the replaced string to check for the number of hyphens.
select *
from yourtable
where len(column_name)-len(replace(column_name,'-',''))=3
and substring(column_name,9,1) not like '%[0-9]%'
If your records have 2 or 3 hyphens, then just do:
where col like '%-%-%-%'
This will get 3 or more hyphens. For exactly 3:
where col like '%-%-%-%' and col not like '%-%-%-%-%'
try this,
declare #t table(col1 varchar(50))
insert into #t values ('A-B'),('A-B-C-D-E'),('A-B-C-D')
select * from
(SELECT *
,(len(col1) - len(replace(col1, '-', ''))
/ len('-')) col2
FROM #T)t4
where col2=3
I have a varchar column that contain numbers (1-99999) and letters (AM0001-BF9999).
Since it has letters so i can't just convert it to int.
Is there a way to maybe use grouping_id to sort this column by numbers (small to large) then follow by letters (alphabetically)?
Thanks..
You need to know what the maximum length of your field is. Assuming 25 characters for illustrative purposes, this will work:
select
v
from (
select
right(space(25) + v,25) as v
from ( values
('1-99999')
,('AM0001-BF9999')
) data(v)
)data
order by v
to yield:
v
-------------------------
1-99999
AM0001-BF9999
You can try using the ISNUMERIC function like this:
select * from test_table
order by
case isnumeric(test_column)
when 1 then convert(int,test_column)
else 999999 end, test_column
Sql fiddle demo.
That's what you get when you denormalize your database schema.
Prefix and number should be stored separately.
That said, this is what I did when I had the same problem:
SELECT * FROM YOUR_TABLE
ORDER BY dbo.GetNumbers(YOUR_FIELD), YOUR_FIELD
Create Function dbo.GetNumbers(#Data VarChar(8000))
Returns int
AS
Begin
Return CAST(Left(
SubString(#Data, PatIndex('%[0-9.-]%', #Data), 8000),
PatIndex('%[^0-9.-]%', SubString(#Data, PatIndex('%[0-9.-]%', #Data), 8000) + 'X')-1) AS int)
End
See also this post for extracting numbers from strings
http://blogs.lessthandot.com/index.php/DataMgmt/DataDesign/extracting-numbers-with-sql-server/