extract sub-string in T-SQL based on condition - sql

I have address in sql column which also contain postcode i.e. as following format
10 westminister way Road, London (NW10 5NQ)
but not all record may have postcode which in case will be like
10 westminister way Road, London
I need to extract post from string which is working fine except following character throw error if postcode doesn't exist which i believe i need to use contain but not sure how to modify existing code to do so
select
,REVERSE(SUBSTRING(REVERSE([address]),2, CHARINDEX('(', REVERSE([address]))-2)) PostCode
,CHARINDEX('(', REVERSE([address]))-2 indexDetail
my question is how to use contain or if condition so
if(CHARINDEX('(', REVERSE([address])) = true then proceed with substring
else ignore record

Using IIF. This will grab everything in the parentheses, regardless of how long the postal code is. I'm not sure if they vary in the UK.
declare #table table ([address] varchar(256))
insert into #table
values
('10 westminister way Road, London (NW10 5NQ)'),
('10 westminister way Road, London')
select
[address],
PostCode = iif(charindex('(',[address]) > 1, substring([address],charindex('(',[address]),charindex(')',[address])),''),
PostalNoParan = iif(charindex('(',[address]) > 1, replace(replace(substring([address],charindex('(',[address]),charindex(')',[address])),'(',''),')',''),'')
from #table

SELECT
[address],
PostalCode = SUBSTRING([address], NULLIF(charindex('(',[address]),0), 256)
FROM #table;
If you need an empty string instead of NULL:
SELECT
[address],
PostalCode = COALESCE(SUBSTRING([address], NULLIF(charindex('(',[address]),0), 256),'')
FROM #table;

How about this?
select (case when address like '% (%)'
then left(right(address, 9), 8)
end) as postcode

Related

Remove everything after a specific special character in SQL Server

This Question is pretty much answered in this forum but for my situation which is exactly the same the answers I find here are not working.
I'm trying to remove all the characters after the pipe " | " in sql server. Any suggestions why it's not working?
query that i'm using:
SELECT left(name, charindex('|',name) -1) from table1
Error:
Invalid length parameter passed to the LEFT or SUBSTRING function.
table1:
name
----
jack| rose|
wil |jo|rdy
karl||jay
jo smith
jjill
raj |kumar
Desired output:
name
----
jack
wil
karl
jo smith
jjill
raj
try:
select LEFT(name,CHARINDEX('|',name + '|')-1)
from table1
Think you're almost there - you just need to filter to ensure you aren't passing a negative number to the LEFT
e.g.,
SELECT left(name, charindex('|',name) -1) from table1
WHERE name LIKE '%|%'
Remember charindex is 0 if it doesn't exist in string, then you subtract 1. This means you're trying to do a LEFT(name, -1) which is invalid.
To get your full output (with all rows, regardless of the | symbol) you can use it in a CASE instead.
SELECT CASE
WHEN [name] LIKE '%|%' THEN left(name, charindex('|',name) -1)
ELSE [name] END AS [name]
from table1
Edit: Here's a db<>fiddle with results.
You can try the below -
SELECT left(name, case when charindex('|',name)=0 then len(name)
else charindex('|',name)-1 end),charindex('|',name)
from tablename
based on your query, its expecting values to have | always. So this will error on name = jo smith'. Use select case to solve this.
declare #str varchar(200)
set #str = 'jo smith'
select case when charindex('|',#str) > 0 then left(#str, charindex('|',#str) -1) else #str end
Instead of using LEFT, use a combination of STUFF and ISNULL.
While LEFT will raise the "Invalid length parameter passed to the left function." error if it gets a negative length parameter,
STUFF will simply return null if it's starting position argument is less than less than 1.
This means that if the original value doesn't contain | and charindex return 0, stuff will simply return null, and you can use ISNULL to return the original value in this case.
First, create and populate sample table (Please save us this step in your future questions):
DECLARE #T TABLE (
[name] varchar(20)
);
INSERT INTO #T ([name]) VALUES
('jack| rose|'),
('wil |jo|rdy'),
('karl||jay'),
('jo smith'),
('jjill'),
('raj |kumar');
The query:
SELECT [name],
ISNULL(STUFF([name], CHARINDEX('|', [name]), LEN([name]), ''), [name]) As Replaced
FROM #T
Results:
name Replaced
jack| rose| jack
wil |jo|rdy wil
karl||jay karl
jo smith jo smith
jjill jjill
raj |kumar raj

SQL - Extracting a substring between two characters

I am trying to pull out the name of a city from a long string in my database. Here is an example of what the data looks like for a few different locations.
"701 MONROE STREET NW RUSSELLVILLE, AL 35653 (34.514971, -87.736372)"
"1825 HOLTVILLE ROAD WETUMPKA, AL 36092 (32.558544, -86.221265)"
I want to create a column for just the Name of the city. My thought was was to take everything Left of the fir comma and right of the following space. I have tried a few different ways to pull this but thing I might be missing something.
SELECT left(Location, CHARINDEX(',', location)) as city FROM table
This is returning everything left of the first comma.
"701 MONROE STREET NW RUSSELLVILLE,
"1825 HOLTVILLE ROAD WETUMPKA,
But now I want to return everything left of the comma and everything Right of the last space in this string and I am stumped as to how I would pull that information correctly. Any help would be appreciated.
Thanks,
Pat
Using REVERSE could work with something along the lines of:
SELECT reverse(
left(
reverse(
left(
Location,
CHARINDEX(',', location)-1
)
),
CHARINDEX(' ', reverse(
left(
Location,
CHARINDEX(',', location)-1
)
)
)
)
)as city FROM table;
Fiddle
If the Google API mentioned in my comment above is not an option. You can download (or even purchase) a ZIP Code database. The cost is nominal. I would suggest the quarterly updates because ZIP Codes change over time (add/edit/delete)
Example
Declare #YourTable table (id int,addr varchar(250))
Insert Into #YourTable values
(1,'701 MONROE STREET NW RUSSELLVILLE, AL 35653 (34.514971, -87.736372)'),
(2,'1825 HOLTVILLE ROAD WETUMPKA, AL 36092 (32.558544, -86.221265)')
Select A.ID
,StreetAddress =left(addr,nullif(charindex(Z.CityName,addr),0)-1)
,Z.CityName
,Z.StateCode
,Z.ZIPCode
From #YourTable A
Join [dbo].[OD-Zip] Z
on Z.ZipCode = substring(addr,nullif(patindex('%[0-9][0-9][0-9][0-9][0-9]%',addr),0),5)
and charindex(Z.CityName,addr)>0
and Z.ZipType='S'
and Z.CityType='D'
Returns
ID StreetAddress CityName StateCode ZIPCode
1 701 MONROE STREET NW Russellville AL 35653
2 1825 HOLTVILLE ROAD Wetumpka AL 36092

How can I create a Query that looks at a field and pulls the 3 characters that appear after a comma

How can I create a Query that looks at a field and pulls the 3 characters that appear after a comma -- EACH entry in this field has a comma and characters after it.
Basically I have a field that has CITY, STATE and sometimes the zipcode after it
I want it to pull the 2 letter State code that appears after the , and the space following the comma
You can use
SELECT SUBSTRING_INDEX(str, delim, count)
See here for documentation.
Standard SQL, as you didn't specify the SQL dialect:
substring(col from position(',' in col)+1 for 3)
Here you go:
SELECT RIGHT(#str, LEN(#str) - CHARINDEX(',', #str) - 1)
in MS SQL Server having the value of a field as 'LAREDOTX,78041', do something like:
DECLARE #Sentence VARCHAR(MAX) = 'LAREDOTX,78041'
SELECT SUBSTRING(#Sentence, CHARINDEX(',', #Sentence)+1 , 3) AS [Second Word]
Getting as result:
Second Word
---------
780
SELECT SUBSTRING_INDEX('www.mytestpage.info','.',2);
for more information
http://www.w3resource.com/mysql/string-functions/mysql-substring_index-function.php

Determine if zip code contains numbers only

I have a field called zip, type char(5), which contains zip codes like
12345
54321
ABCDE
I'd like to check with an sql statement if a zip code contains numbers only.
The following isn't working
SELECT * FROM S1234.PERSON
WHERE ZIP NOT LIKE '%'
It can't work because even '12345' is an "array" of characters (it is '%', right?
I found out that the following is working:
SELECT * FROM S1234.PERSON
WHERE ZIP NOT LIKE ' %'
It has a space before %. Why is this working?
If you use SQL Server 2012 or up the following script should work.
DECLARE #t TABLE (Zip VARCHAR(10))
INSERT INTO #t VALUES ('12345')
INSERT INTO #t VALUES ('54321')
INSERT INTO #t VALUES ('ABCDE')
SELECT *
FROM #t AS t
WHERE TRY_CAST(Zip AS NUMERIC) IS NOT NULL
Using answer from here to check if all are digit
SELECT col1,col2
FROM
(
SELECT col1,col2,
CASE
WHEN LENGTH(RTRIM(TRANSLATE(ZIP , '*', ' 0123456789'))) = 0
THEN 0 ELSE 1
END as IsAllDigit
FROM S1234.PERSON
) AS Z
WHERE IsAllDigit=0
DB2 doesnot have regular expression facility like MySQL REGEXP
USE ISNUMERIC function;
ISUMERIC returns 1 if the parameter contains only numbers and zero if it not
EXAMPLE:
SELECT * FROM S1234.PERSON
WHERE ISNUMERIC(ZIP) = 1
Your statement doesn't validate against numbers but it says get everything that doesn't start with a space.
Let's suppose you ZIP code is a USA zip code, composed by 5 numbers.
db2 "with val as (
select *
from S1234.PERSON t
where xmlcast(xmlquery('fn:matches(\$ZIP,''^\d{5}$'')') as integer) = 1
)
select * from val"
For more information about xQuery:fn:matches: http://pic.dhe.ibm.com/infocenter/db2luw/v10r5/topic/com.ibm.db2.luw.xml.doc/doc/xqrfnmat.html
mySql does not have a native isNumberic() function. This would be pretty straight-forward in Excel with the ISNUMBER() function, or in T-SQL with ISNUMERIC(), but neither work in MySQL so after a little searching around I came across this solution...
SELECT * FROM S1234.PERSON
WHERE ZIP REGEXP ('[0-9]')
Effectively we're processing a regular expression on the contents of the 'ZIP' field, it may seem like using a sledgehammer to crack a nut and I've no idea how performance would differ from a more simple approach but it worked and I guess that's the point.
I have made more error-prone version based on the solution https://stackoverflow.com/a/36211270/565525, added intermedia result, some examples:
select
test_str
, TRIM(TRANSLATE(replace(trim(test_str), ' ', 'x'), 'yyyyyyyyyyy', '0123456789'))
, case when length(TRIM(TRANSLATE(replace(trim(test_str), ' ', 'x'), 'yyyyyyyyyyy', '0123456789')))=5 then '5-digit-zip' else 'not 5d-zip' end is_zip
from (VALUES
(' 123 ' )
,(' abc ' )
,(' a12 ' )
,(' 12 3 ')
,(' 99435 ')
,('99323' )
) AS X(test_str)
;
The result for this example set is:
TEST_STR 2 IS_ZIP
-------- -------- -----------
123 yyy not 5d-zip
abc abc not 5d-zip
a12 ayy not 5d-zip
12 3 yyxy not 5d-zip
99435 yyyyy 5-digit-zip
99323 yyyyy 5-digit-zip
Try checking if there's a difference between lower case and upper case. Numerics and special chars will look the same:
SELECT *
FROM S1234.PERSON
WHERE UPPER(ZIP COLLATE Latin1_General_CS_AI ) = LOWER(ZIP COLLATE Latin1_General_CS_AI)
Here's a working example for the case where you'd want to check zip codes in a range. You could use this code for inspiration to make a simple single post code check, if you want:
if local_test_environment?
# SQLite supports GLOB which is similar to LIKE (which it only has limited support for), for matching in strings.
where("(zip_code NOT GLOB '*[^0-9]*' AND zip_code <> '') AND (CAST(zip_code AS int) >= :range_start AND CAST(zip_code AS int) <= :range_finish)", range_start: range_start, range_finish: range_finish)
else
# SQLServer supports LIKE with more advanced matching in strings than what SQLite supports.
# SQLServer supports TRY_PARSE which is non-standard SQL, but fixes the error SQLServer gives with CAST, namely: Conversion failed when converting the nvarchar value 'US-19803' to data type int.
where("(zip_code NOT LIKE '%[^0-9]%' AND zip_code <> '') AND (TRY_PARSE(zip_code AS int) >= :range_start AND TRY_PARSE(zip_code AS int) <= :range_finish)", range_start: range_start, range_finish: range_finish)
end
Use regex.
SELECT * FROM S1234.PERSON
WHERE ZIP REGEXP '\d+'

Update one column from substring of another column

I have an existing column that I would like to take a subset of and insert into a second (new) column in the same table.
e.g. MyTable.[FullName] (existing column) contains a string like "P-13-146 PS - Goodyear - Tire repair"
I created a new column, MyTable.[ShortName] that I want to insert a substring of the value from the first column into ("P-13-146 PS"). The problem is that the length of the substring is different for each full name. The only real consistency is that I want up to the second whitespace character.
I am trying to resolve the following:
UPDATE [MyTable] SET [ShortName] = ???
Try this:
declare #exp varchar(200)
set #exp='P-13-146 PS - Goodyear - Tire repair'
select RTRIM(SUBSTRING(#exp,1,CHARINDEX(' ',#exp,charindex(' ',#exp)+1)))
Just combine the string manipulation functions until you get what you want:
SELECT
CASE WHEN CHARINDEX(' ',FullName, CHARINDEX(' ', FullName)+1) = 0 THEN FullName
ELSE SUBSTRING(FullName, 1, CHARINDEX(' ',FullName, CHARINDEX(' ', FullName)+1)-1)
END ShortName
FROM MyTable
The first part of the CASE statement is for names that have fewer than two spaces.