TSQL - Locating first occurrence of value in a string - sql-server-2005

I need to run a simple select statement for a column called AddrZip to show all records that contain '1/2 ' after the first space in the column. In Access 2007 it would be: **Left([Names],InStr(1,[Names]," ")-1), but can't find out how to do it in SQL 2005. All help will be appreciated.

First, look for records with a ' ':
CHARINDEX(' ', [AddrZip]) > 0
Then look for records with a '1/2' occurring after the ' '
CHARINDEX('1/2', [AddrZip], CHARINDEX(' ', [AddrZip])) > 0
SELECT *
FROM ( SELECT *
FROM [Addresses]
WHERE CHARINDEX(' ', [AddrZip]) > 0
) x
WHERE CHARINDEX('1/2', [x].[AddrZip], CHARINDEX(' ', [AddrZip])) > 0
This "simplified" version may work:
SELECT *
FROM [Addresses]
WHERE CHARINDEX(' ', [AddrZip]) > 0
AND CHARINDEX('1/2', [x].[AddrZip], CHARINDEX(' ', [AddrZip])) > 0
If you want to find occurrences of '1/2' that are immediately preceded by a ' ' where the ' ' is the very first space in the string, then use the following code:
SELECT *
FROM [Addresses]
WHERE CHARINDEX(' ', [AddrZip]) > 0
AND CHARINDEX(' ', [AddrZip]) = CHARINDEX(' 1/2', [x].[AddrZip])
Avoid LIKE operators if at all possible. They are notoriously slow.

Try this -
select * from table where addrZip like '%\ 1/2%' escape '\'

Related

How to get the first letter of each word in SQL

I tried to run this query to get the initial letter of each word, and it worked for strings of 4 words, yet if the string has only two words, it duplicates the second word's initial.
select
substring(column_name, 1, 1) +
case
when 0 <> charindex(' ', column_name) + 1
then substring(column_name, charindex(' ',column_name) + 1, 1)
else ''
end +
case
when 0 <> charindex(' ', column_name, charindex(' ', column_name) + 1)
then substring(column_name, charindex(' ', column_name, charindex(' ', column_name) + 1) + 1, 1)
else ''
end +
case
when 0 <> charindex(' ', column_name, charindex(' ', column_name, charindex(' ', column_name) + 1) + 1)
then substring(column_name, charindex(' ', column_name, charindex(' ', column_name, charindex(' ', column_name) + 1) + 1) + 1, 1)
else ''
end
from table_name
You didn't specify which RDBMS you are using. This should work in SQL Server:
drop table if exists table_name
create table table_name (
column_name varchar(255)
)
insert table_name
values ('See Jane')
, ('See Jane run')
, ('See Jane run and jump over the lazy dog.')
select stuff((SELECT '' + t2.fc
from (
select left(str.value, 1) fc
, charindex(' ' + str.value + ' ', ' ' + t.column_name + ' ') idx
from string_split(t.column_name, ' ') str
) t2
order by t2.idx
FOR XML PATH('')
), 1, 0, '') as FirstChars
from table_name t
The idx column is used to order the ouptut because string_split does not promise to return the results in any particular order. Thanks to Aaron Bertrand - https://dba.stackexchange.com/questions/207274/string-split-and-ordered-results
Given the use of charindex in your question, I'm assuming you are using SQL Server. The CTE generates a tall view of your data using string_split function, with each letter on it's own row. We then select from it and group by id, and apply the string_agg function to place back into a single row.
Password guessing?
create table my_data (
id integer,
comments varchar(50)
);
insert into my_data (id, comments) values
(1, 'Thank goodness its friday'),
(2, 'I want 2 scoops of ice cream');
select * from my_data;
id
comments
1
Thank goodness its friday
2
I want 2 scoops of ice cream
with cte (id, first_char) as (
select id, substring(ss.value, 1, 1) as first_char
from my_data
cross apply string_split(comments, ' ')ss
)
select t.id,
string_agg(t.first_char, ',') as letters_delimited,
string_agg(t.first_char, '') as letters_not_delimited
from cte t
group by t.id
id
letters_delimited
letters_not_delimited
1
T,g,i,f
Tgif
2
I,w,2,s,o,i,c
Iw2soic
fiddle here
You can extend your approach with recursion
WITH cte_name AS (
select CONVERT(nvarchar(max), substring(column_name, 1, 1)) conc,
column_name n,
charindex(' ', column_name, 0) pos
from table_name
UNION ALL
select conc + substring(n, pos + 1, 1) as conc,
n,
charindex(' ', n, pos + 1) pos
from cte_name where pos > 0
)
SELECT *
FROM cte_name
where pos = 0;

Trim extra white space within column

I have the following select that is converting a name from Lastname, Firstname format into Firstname Lastname format. It seems to be adding extra white space between the first name and the last name
SELECT substring(D.NAME, charindex(',', replace(D.NAME, ' ', '')) + 1, len(D.NAME))
+ ' '
+ left(D.NAME, charindex(',', D.NAME) -1) AS First_Last
FROM TEST_TABLE D
Here are a few examples of the output I'm getting now:
Johnnyyy Smithsonnn
Kimmey Test1
Denise Stuffing
Desired Format (single space between first and last name):
Johnnyyy Smithsonnn
Kimmey Test1
Denise Stuffing
I tend to like this technique. In this example we use a rare replacement pattern of †‡, but you can use <> and ><
Note: The outer ltrim(rtrim( ... )) is optional, I keep it as a "just in case".
Example
Select NewValue = ltrim(rtrim(replace(replace(replace([Name],' ','†‡'),'‡†',''),'†‡',' ')))
From YourTable
Returns
NewValue
Johnnyyy Smithsonnn
Kimmey Test1
Denise Stuffing
Maybe there are names with or without , or with or without spaces after the ,, or other inconsistencies.
Anyway you can use ltrim(rtrim()) before concatenating:
select
case
when d.name like '%,%' then
ltrim(rtrim(substring(d.name, charindex(',', name) + 1, len(d.name))))
+ ' ' +
ltrim(rtrim(left(D.NAME, charindex(',', d.name) -1)))
when d.name like '% %' then
ltrim(rtrim(substring(d.name, charindex(' ', name) + 1, len(d.name))))
+ ' ' +
ltrim(rtrim(left(D.NAME, charindex(' ', d.name) -1)))
else ltrim(rtrim(d.name))
end AS First_Last
Try:
select ltrim(rtrim(left(D.NAME, charindex(',', D.NAME, 0) - 1)))
+ ' '
+ ltrim(rtrim(right(D.NAME, len(D.NAME) - charindex(',', D.NAME, 0))))
from TEST_TABLE D
This worked on some test data I used below:
insert into #Test ([Name]) values ('Johnnyyy, Smithsonnn')
insert into #Test ([Name]) values ('Kimmey, Test1')
insert into #Test ([Name]) values ('Denise, Stuffing')
Which gives the intended result:
Johnnyyy Smithsonnn
Kimmey Test1
Denise Stuffing
I think you intend to do the replace of spaces after extracting the name. So:
SELECT (replace(left(D.NAME, charindex(',', D.NAME + ',') + 1), ' ', '') +
' ' +
left(D.NAME, charindex(',', D.NAME + ',') - 1)
) AS First_Last
FROM TEST_TABLE D;
This also adds a comma for the charindex() so the comma is optional.

SQL-Server: Replace except first and last characters

Is there any ways to SELECT the first and last 2 characters and REPLACE all the other characters with * as shown below?
WA***RT
EX*** ***IL
CH***ON
BE******* *****AY
AP*LE
Thanks in advance!
Spaces skipped:
SELECT
name,
[hidden] = CASE WHEN LEN(name) <= 4 THEN name
ELSE CONCAT(LEFT(name, 2),REPLICATE('*', LEN(name)- 2),RIGHT(name,2))
END
FROM #tab;
If you need spaces and there is only one you can use:
SELECT name,
[hidden] = CASE
WHEN LEN(name) <= 4 THEN name
WHEN CHARINDEX(' ', name) > 0
THEN STUFF(CONCAT(LEFT(name, 2),REPLICATE('*', LEN(name) - 2) ,
RIGHT(name,2)), CHARINDEX(' ', name),1, ' ')
ELSE CONCAT(LEFT(name, 2),REPLICATE('*', LEN(name) - 2) ,RIGHT(name,2))
END
FROM #tab;
LiveDemo
If you use version lower than SQL Server 2012 concatenate string with +.
select left(col, 2) + REPLICATE('*',len(col)-4) + right(col,2) from table;
You can use STUFF.
SELECT STUFF(col, 3, LEN(col)-4, REPLICATE('*',LEN(col)-4))
This doesn't preserve spaces.
To preserve N spaces, you can simply "add back spaces" with STUFF again:
SELECT col,
masked =
coalesce(
-- handle 2 spaces
STUFF(STUFF(
STUFF(col, 3, LEN(col)-4, REPLICATE('*',LEN(col)-4)),
CHARINDEX(' ', col), 1, ' '),
CHARINDEX(' ', col, CHARINDEX(' ', col)+1), 1, ' '),
-- handle 1 spaces
STUFF(
STUFF(col, 3, LEN(col)-4, REPLICATE('*',LEN(col)-4)),
CHARINDEX(' ', col), 1, ' '),
-- normal masking
STUFF(col, 3, LEN(col)-4, REPLICATE('*',LEN(col)-4)),
-- too short to mask
col
)
Demo

SQl string split (parse) on space where some field values have no space

I've been trying to split a string value in my query to return the first part of a two part postcode in a new column. Some values have only the first part, and some have both. After a bit of searching I found this code:
SELECT
TblPLSSU.PLSSUPostcode
,SUBSTRING(TblPLSSU.PLSSUPostcode, 1, CHARINDEX(' ', TblPLSSU.PLSSUPostcode)) AS PCode
FROM
TblPostcodes
This happily splits the values that have two parts to the postcode but it seems to be ignoring the single part post codes.
For example, values for TblPLSSU.PLSSUPostcode might be:
EH1 1AB
EH2
I want to return the values
EH1
EH2
But with the code above I am only getting EH1
Thanks
Eils
Use case to pick up post codes as-is when they don't have a space separated value.
SELECT
PLSSUPostcode
,case when CHARINDEX(' ', PLSSUPostcode) > 0
then SUBSTRING(PLSSUPostcode, 1, CHARINDEX(' ', PLSSUPostcode))
else PLSSUPostcode end AS PCode
FROM
TblPostcodes
Use case as well:
SELECT TblPLSSU.PLSSUPostcode,
(CASE WHEN TblPLSSU.PLSSUPostcode LIKE '% %'
THEN SUBSTRING(TblPLSSU.PLSSUPostcode, 1, CHARINDEX(' ', TblPLSSU.PLSSUPostcode))
END) AS PCode
FROM . . .
A little trick with STUFF function. This works because of CHARINDEX returns index of the first occurrence. So you are just adding space to strings and replacing all symbols from first occurrence till the end with empty string:
DECLARE #t TABLE(v VARCHAR(20))
INSERT INTO #t VALUES('EH1 1AB'), ('EH2')
SELECT STUFF(v + ' ', CHARINDEX(' ', v + ' '), LEN(v), '')
FROM #t
Another version:
SELECT SUBSTRING(v + ' ', 1, CHARINDEX(' ', v + ' ') - 1)
FROM #t
Output:
EH1
EH2

Extracting first word from a string in SQL, where the string is a single word

I am able to extract the first word from a string, using ANSI SQL, like this:
SELECT SUBSTRING(name FROM 1 FOR POSITION(' ' IN name)) AS first_name
However, if the original string is only one word long (ie, if there is no space), it returns an empty substring.
How can the above query be adapted to solve this problem?
Thanks in advance.
I'm sure there is a cleaner way to do it, but this works.
DECLARE #tbl TABLE (i varchar(100));
INSERT INTO #tbl ( i )
VALUES ('hello'), ('hello space here');
SELECT *,
SUBSTRING(i, 0, CASE CHARINDEX(' ', i)
WHEN 0 THEN LEN(i) + 1
ELSE CHARINDEX(' ', i)
END)
FROM #tbl
Simply but messy solution - add a space on the end:
SELECT SUBSTRING((name || ' ') FROM 1 FOR POSITION(' ' IN (name || ' '))) AS first_name
Use a conditional if statement.
For a MySQL/SQL Server answer:
SELECT IF(INSTR(name, ' ') >0, LEFT(name, INSTR(name, ' ') - 1), name) AS firstname
For Oracle:
SELECT IF(INSTRB(name, ' ', 1, 1) >0, SUBSTR(name, 1, INSTRB(name, ' ', 1, 1) - 1), name) AS firstname
I personally prefer the Regexp query for this, but below query also works.
You basically append a space at the end of the string and search for the position of the space using INSTR.
ORACLE:
select substr(Var1, 0,INSTR(Var1||' ',' ')) from table-name;
Replace Var1 with the column-name or string you are evaluating.
Put Column Name in place of #foo
DECLARE #Foo VARCHAR(50) = 'One Two Three'
SELECT
CASE
--For One Word
WHEN CHARINDEX(' ', #Foo, 1) = 0 THEN #Foo
--For multi word
ELSE SUBSTRING(#Foo, 1, CHARINDEX(' ', #Foo, 1) - 1)
END
DECLARE #test VARCHAR(50) = 'One Two Three'
SELECT SUBSTRING(LTRIM(#test),1,(CHARINDEX(' ',LTRIM(#test) + ' ')-1))
you can use this to get the first word of a string.initcap
will get you the first letter capital.
SELECT SUBSTR(column_1, 1, INSTR(column_1, ' ', 1,1) ) FROM table_name WHERE column_1= initcap('your string');