SQL Server: Substring based on first two characters being a number - sql

I have a text field and want to pull out an ID number from the field - the ID always starts with an 8 and is 12 characters long (e.g 899900014658), the current code uses the substring method below:
substring(textfield,charindex('8',textfield),12) as extractedID
This pulls out anything starting with an 8 though so I'm getting results like '8 am', '8 February' etc in the extractedID field.
Is there a method of extracting anything starting with an 8 where the second and third characters are also a number?
edit - solved using PATINDEX
SUBSTRING(SubmissionDiaryEntry,(PATINDEX('%8[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]%',SubmissionDiaryEntry)),12)

If I understand your question:
Select *
From YourTable
Where textfield like '8[0-9][0-9]%'

Ckeck below, it may help:
declare #textfield nvarchar(20) = '845456798234'
select case when substring(#textfield, 2, 1) like '[0-9]'
and substring(#textfield, 3, 1) like '[0-9]'
then substring(#textfield,charindex('8',#textfield),12)
else 'not valid'
end
as extractedID
-- test
set #textfield = '8r5456798234'
select case when substring(#textfield, 2, 1) like '[0-9]'
and substring(#textfield, 3, 1) like '[0-9]'
then substring(#textfield,charindex('8',#textfield),12)
else 'not valid'
end
as extractedID
however John's answer is much simplier and it looks like exactly what you are looking for.
Below is just to clarify..., using John's script, answer to your issue would be:
select substring(textfield,charindex('8',textfield),12) as extractedID
from yourTable
where textfield like '8[0-9][0-9]%'

Related

How to ignore specific string value when using pattern and patindex function in SQL Server Query?

I have this query here.
WITH Cte_Reverse
AS (
SELECT CASE PATINDEX('%[^0-9.- ]%', REVERSE(EmailName))
WHEN 0
THEN REVERSE(EmailName)
ELSE left(REVERSE(EmailName), PATINDEX('%[^0-9.- ]%', REVERSE(EmailName)) - 1)
END AS Platform_Campaign_ID,
EmailName
FROM [Arrakis].[xtemp].[Stage_SendJobs_Marketing]
)
SELECT REVERSE(Platform_Campaign_ID) AS Platform_Campaign_ID, EmailName
FROM Cte_Reverse
WHERE REVERSE(Platform_Campaign_ID) <> '2020'
AND REVERSE(Platform_Campaign_ID) <> ''
AND LEN(REVERSE(Platform_Campaign_ID)) = 4;
It is working for the most part, below is a screenshot of the result set.
The query I posted above extracts the 4 numbers to the right out of the initial value that is set for the column I am extracting out of. But I am unable to figure out how I can also have the query ignore cases when the right most value is -v2, -v1, etc. essentially anything with -v and whatever number version it is.
If you want four digits, then one method is:
select substring(emailname, patindex('%[0-9][0-9][0-9][0-9]%', emailname), 4)

Return anything but a space with INSTR or CHARINDEX

I need to return results where a space is NOT used in the 3rd to last position (so from the right). Attempting to identify records where a US state acronym was not used.
JOHN MN
MATT HI
TERRY ARKANSAS
I'm running this through DBVisualizer and I am stumped. I've tried to add some CHARINDEX, RIGHT...etc, but no combination is working.
Ideally, it would look something like:
SELECT INSTR(COLUMN, **<>** ' ', -3) FROM TABLE
try Something like this :
select * from yourtable
where
case when length(trim(yourcolumn))>2 and right(trim(yourcolumn), 3) like ' %' then 1 else 0 end =0
or this
select * from yourtable
where trim(yourcolumn) not like '% __'
Try this:
SELECT IIF(len(RIGHT(COLUMN,LEN(COLUMN)-3))=LEN(REPLACE(RIGHT(COLUMN,LEN(COLUMN)-3),' ','')),0,1)
If it returns 0, that means it does not have a blank value from 3rd to the last position.
If it returns 1, that means it does have a blank.

SQL Server - select substring of all characters following last hyphen

I am working with a database of products, trying to extract the product color from a combined ID/color code column where the color code is always the string following the last hyphen in the column. The issue is that the number of hyphens, product ID, and color code can all be different.
Here are four examples:
ABC123-001
BCD45678-0165
S-XYZ999-M2235
A-S-ABC123-001
The color codes in this case would be 001, 0165, M2235, and 001. What would be the best way to select these into their own column?
I think the following does what you want:
select right(col, charindex('-', reverse(col)) - 1)
In the event that you might have no hyphens in the value, then use a case:
select (case when col like '%-%'
then right(col, charindex('-', reverse(col)) - 1)
else col
end)
It is great to check whether the hyphen exists or not in the string, to avoid the following error:
Invalid length parameter passed to the right function.
SELECT CASE WHEN Col like '%\%' THEN RIGHT(Col,CHARINDEX('\',REVERSE(Col))-1) ELSE '' END AS ColName

Using conditions to specify groups for GROUP BY

I'm not even sure if this is possible using SQL, but I'm completely stuck on this problem. I have a table like this:
Total Code
212 XXX_09_JUN
315 XXX_7_JUN
68 XXX_09_APR
140 XXX_AT_APR
729 XXX_AT_MAY
I need to sum the "total" column grouped by the code. The issue is that "XXX_09_JUN" and "XXX_7_JUN" and "XXX_09_APR" need to be the same group.
I was able to accomplish this by creating a new column where I assigned values based on the row's code, but since this needs to be done on multiple tables with millions of entries, I can't use that method.
Is there some way that I could group the rows based on a condition such as:
WHERE Code LIKE '%_09_%' OR Code LIKE '%_7_%'
This is not the only condition - I need about 10 conditions like this. Sorry if that doesn't make sense, I'm not sure how to explain this...
Also, if this can be accomplished using Visual Studio 2008 and SSRS more easily, that would work as well because that is the final goal of this query.
Edit: To clarify, this would be the ideal result:
Total Code
595 had_a_number
869 had_at
One option is to use a CASE expression:
GROUP BY CASE
WHEN Code LIKE '%!_09!_%' ESCAPE '!'
THEN 'had_a_number'
WHEN Code LIKE '%!_7!_%' ESCAPE '!'
THEN 'had_a_number'
WHEN Code LIKE '%!_AT!_%' ESCAPE '!'
THEN 'had_at'
ELSE 'other'
END
Add however many WHEN conditions to assign whatever condition to a "group".
Note that the underscore is a wildcard character for the LIKE operator. An underscore will match any single character. To search for a literal underscore, you would need to "escape" the underscore within the string literal.
'A_12_E' LIKE '%_12_%' => TRUE
'AB12DE' LIKE '%_12_%' => TRUE
'A_12_E' LIKE '%!_12!_%' ESCAPE '!' => TRUE
'AB12DE' LIKE '%!_12!_%' ESCAPE '!' => FALSE
SQL Fiddle
MS SQL Server 2008 Schema Setup:
CREATE TABLE TEST_TABLE(Total INT, Code VARCHAR(20))
GO
INSERT INTO TEST_TABLE VALUES
(212, 'XXX_09_JUN'),
(315, 'XXX_7_JUN'),
(68, 'XXX_09_APR'),
(140, 'XXX_AT_APR'),
(729, 'XXX_AT_MAY')
GO
Query 1:
SELECT SUM(Total) Total
,CASE
WHEN Code LIKE '%_%[0-9]%_%'
THEN 'had a number'
WHEN Code NOT LIKE '%_%[0-9]%_%'
THEN 'had at'
END AS Code
FROM TEST_TABLE
GROUP BY CASE
WHEN Code LIKE '%_%[0-9]%_%'
THEN 'had a number'
WHEN Code NOT LIKE '%_%[0-9]%_%'
THEN 'had at'
END
Results:
| TOTAL | CODE |
|-------|--------------|
| 595 | had a number |
| 869 | had at |
Heres a ridiculous way to solve your problem:
SQLFiddle
Schema:
CREATE TABLE tblTotalCode(
Total INTEGER,
Code VARCHAR(15)
)
INSERT INTO tblTotalCode VALUES(212,'XXX_09_JUN')
,(315,'XXX_7_JUN')
,(68, 'XXX_09_APR')
,(140,'XXX_AT_APR')
,(729,'XXX_AT_MAY')
Code:
SELECT CASE WHEN(LEFT(RIGHT(Code, LEN(Code) - CHARINDEX('_', Code, 1)), CHARINDEX('_', RIGHT(Code, LEN(Code) - CHARINDEX('_', Code, 1)), 1) - 1)) IN ('09','7') THEN '09 or 7' ELSE 'Not 09 or 7' END AS '09 or 7 Group'
, SUM(Total) AS 'Total'
FROM tblTotalCode
Group By CASE WHEN(LEFT(RIGHT(Code, LEN(Code) - CHARINDEX('_', Code, 1)), CHARINDEX('_', RIGHT(Code, LEN(Code) - CHARINDEX('_', Code, 1)), 1) - 1)) IN ('09','7') THEN '09 or 7' ELSE 'Not 09 or 7' END

Max of a part of split string

I have, in my DB oracle 10g, a field that contains references.
It's stored as : name/yyyy/mm/number
The new number, is the max number found in the part mm/number.
So, for now, I have a split of my string that gives me a list of str_array like this :
str_array(name, yyyy, mm, number)
I'd like, with this, found max number, for the couple mm/number.
Is this possible to do this?
Can I have something like :
SELECT MAX(split(reference, '/').lastPartOfArray) into nb
FROM table
where lastPartOfArray-1 = sysdate.month;
Data samples :
Smith/2013/12/1
Smith/2013/11/1
Smith/2013/12/3
Jones/2013/12/6
Smith/2013/12/3
Jones/2013/11/7
Since we are in the month 12, a max on those data must give me 6 into nb.
The number part, has no limit, it can be 1000, 10000...
The part Jones/2013 doesn't really matter for the number. But I can't have the same number, for a month.
My apologies, I don't know if this is possible, so I tried to write what I want in the query.
Is this possible, or should I create more than one field in my table(name/yyyy, mm, number)?
edit : valex answer and some custom
select MAX(CAST(SUBSTR(num,INSTR(num,'/')+9,1000) as Int))
from T
where num like TO_CHAR(sysdate,'%/YYYY/MM/%')
So this, count searching first occurence.
select MAX(CAST(SUBSTR(num,INSTR(num,'/',1 ,n)+1,1000) as Int))
from T
where num like TO_CHAR(sysdate,'%/YYYY/MM/%')
This found the n occurence of the char.
This is a helpful solution in other cases.
To get a maximum you should convert this last part into INT values otherwise you can get not right results because of STRING comparing rules will be used.
As soon as /YYYY/MM/ has got a fixed length = 9 so we can find first \ position and add 9 to this position to find a last part number substring start.
Here is an example:
select MAX(CAST(SUBSTR(num,INSTR(num,'/')+9,1000) as Int))
from T
where num like TO_CHAR(sysdate,'%/YYYY/MM/%')
SQLFiddle demo
Also you can exclude wrong formatted values from this query to avoid conversion errors using the following way:
select MAX(CAST(SUBSTR(num,INSTR(num,'/')+9,1000) as Int))
from T
where num like TO_CHAR(sysdate,'%/YYYY/MM/%')
AND
LENGTH(TRIM(TRANSLATE(SUBSTR(num,INSTR(num,'/')+9,1000),
' 0123456789', ' '))) is null
SQLfiddle demo
Try this:
SELECT
MAX(SUBSTR(num, INSTR(num, '/', 1, 3) + 1))
FROM ref
WHERE
SUBSTR(num, INSTR(num, '/', 1, 2) + 1, INSTR(num, '/', 1, 3) - INSTR(num, '/', 1, 2) - 1) = TO_CHAR(sysdate, 'MM')
Sample: http://sqlfiddle.com/#!4/1b03a/1