How to extract numbers from a string SQL - sql

Ts there a way to extract numbers from a string?
In my database there is a column called Reference and it contains multiple numbers
CM|319|14163|||109|405000
Is there a way to get the first number like this?
select CM|%s|... as ParentId from table
So the output should be 319
And maybe even multiple like
select CM|...|%s|... as SiblingId, CM|%s|... as ParentId from table
14163 319

We might be able to use PATINDEX here along with a substring operation. We can find the position of the first number in the string, and then take a substring until one position past the first occurrence of a number followed by a pipe character.
SELECT SUBSTRING(val,
PATINDEX('%[0-9]%', val),
PATINDEX('%[0-9]|%', val) - PATINDEX('%[0-9]%', val) + 1)
FROM yourTable;
Demo
Data:
WITH yourTable AS (
SELECT 'CM|319|14163|||109|405000' AS val
)

if using sql2017 or later...
maybe?
CREATE TABLE #yourtable(
reference VARCHAR(50) NOT NULL PRIMARY KEY
);
INSERT INTO #yourtable(reference) VALUES ('CM|319|14163|||109|405000');
INSERT INTO #yourtable(reference) VALUES ('CMff123|14163|||109AA|4ZXC05000');
SELECT reference,
TRIM(REPLACE(TRANSLATE(reference,'abcdefghijklmnopqrstuvwxyz',REPLICATE('|',26)),'|',' ')) AS extracted
FROM #yourtable

Related

extract multiple matches from varchar or text column as rows from MariaDB

I have a string (varchar ) column in my DB and I would like to use SQL to so some simple group matching and extract the matches into rows. Is there a way to accomplish this in plain SQL in mariaDB without a stored procedure or custom function?
Example:
my_string ="this is a test string with x12345 and y1264 ...";
I am looking for something like this to extract all numbers starting with x or y into rows.
SELECT REGEXP_SUBSTR("[xy][0-9]+") from my_string;
Expected result:
x12345
y1264
The reason I need the rows is that this will be part of a bigger query where I join these rows on a key in another table.
My above query only returns 1 row, the 1st result
x12345
Is there a way to obtain all matches?
You may use JSON_TABLE to extract all words in your string, then check if these words start with x or y and are followed by numbers.
You can simply convert your string to a JSON format by enclosing it with square brackets, enclosing each word with double quotations, and replacing every single space with a comma. So you can use this code to do that CONCAT('["', REPLACE(myTxt, ' ', '","'), '"]').
Then you can use the JSON_TABLE as the following:
create table tbl(id int, myTxt TEXT);
insert into tbl values
(1, 'this is a test string with x12345 and y1264'),
(2, 'this is a test xtest ytest string with x11111 and y11111 and x22222 and y22222');
SELECT id,
ROW_NUMBER() OVER (PARTITION BY id ORDER BY W.rowid) num_order,
W.xy_val
FROM tbl
CROSS JOIN JSON_TABLE
(
CONCAT('["', REPLACE(myTxt, ' ', '","'), '"]'),
'$[*]'
COLUMNS
(
rowid FOR ORDINALITY,
xy_val VARCHAR(32) PATH '$'
)
) W
WHERE W.xy_val REGEXP '[xy][0-9]'
See demo

how to split the column into multiple columns using delimeter in SQL server?

I have below column in my table
I would like to split the column using decimeter '-' and create a new column in SQL Server.
Required output
I used parsename in the query but no success.
select
ID,
PARSENAME(ID,'-', 1) AS EmployeeID from timeus;
I checked other posts but not able to solve it.
Can anyone advise how to to split in SQL server?
You can use this script to split the data:
CREATE TABLE dbo.NotProvided
(
Category NVARCHAR(50)
);
GO
INSERT INTO dbo.NotProvided
(
Category
)
VALUES
('103-Local IT-HHH'),
('102-HDHD-2737'),
('104-HHFY-XXX');
SELECT *,
LEFT(Category, CHARINDEX('-', Category) - 1) as Id
FROM dbo.NotProvided;
You can use parsename like you have tried, like so:
select ID, ParseName(Replace(ID, '-', '.'), 3) AS EmployeeID
from timeus;
You can use substring function in MSSQL server.
Select Category,SUBSTRING(Category,1,3) As Employeeid From NotProvided;

Get maximum value in a column in sql query if the column is alphanumeric

This is the table which I have by name project and it contains 3 columns:
estimateId
name
projectName
I want to fetch data from SQL database based on maximum value of estimateId
but here estimateid is alphanumeric. How can I achieve this.
I need a SQL query to achieve this:
For example estimateId contains values like:
Elooo1
Elooo2
......
Elooo10
and so on. So how can I achieve this?
Setup Testing Data
DECLARE #tmpTable TABLE ( estimateId NVARCHAR(MAX));
INSERT into #tmpTable(estimateId) VALUES ('Elooo1'),('Elooo2'),('Elooo3'),('Elooo4'),('Elooo5'),('Elooo6');
Split data based on the pattern
SELECT T.prefix AS prefix, MAX(T.suffix) AS suffix, MAX(estimateId) AS estimateId FROM (SELECT estimateId,LEFT(estimateId, PATINDEX('%[a-zA-Z][^a-zA-Z]%', estimateId )) AS prefix,LTRIM(RIGHT(estimateId, LEN(estimateId) - PATINDEX('%[a-zA-Z][^a-zA-Z]%', estimateId ))) As suffix FROM #tmpTable) T GROUP BY T.prefix
Result
prefix suffix estimateId
Elooo 6 Elooo6
Reference
split alpha and numeric using sql
I just started SQL like today.. so i'm totally a newbie, but I think I could solve your problem. I would do something like this
SELECT name, projectName FROM table ORDER BY estimateId ASC
or (I think you will need ORDER BY ... DESC)
SELECT name, projectName FROM table ORDER BY estimateId DESC
You seem to be looking to extract the numeric part of the strings. Assuming that the strings have variable length, and that the numbers are always at the end, you can do:
try_cast(
substring(estimateId, patindex('%[0-9]%', estimateId), len(estimateId))
as int
)
This captures everything from the the first number in the string to the end of the string, and attempts to convert it to a number (if the conversion fails, try_cast() returns null rather than raising an error).
It is not very clear what you want to use this information for. For example, if you wanted to sort your data accordingly, you would do:
select *
from mytable
order by try_cast(
substring(estimateId, patindex('%[0-9]%', estimateId), len(estimateId))
as int
)

how to replace a column value which is separated by comma in SQL

I am having a table which is having a column named as CDR.
In that CDR column we have values stored as comma separated like 20,5,40,10,30
I just need to replace last value(here it is 30) to 0 in every row.
Can someone suggest me how can we do?
Thanks
If you are able, first correct the database design as the table is not in first normal form. It is bad design to have more than one value stored in one column, as evidenced by you having to ask this question. :-) Having said that, I have to deal with vendor data that has the same issue that is beyond my control to change, so in Oracle 11g I would do this:
update table_name
set CDR = regexp_replace(CDR, '(.*,)\d+$', '\10');
The regex matches and remembers all characters up to and including the last comma before one or more digits right before the end of the string. The replace string is the remembered part referenced by the \1, referring to the first grouping of characters inside parenthesis), plus the 0.
If you are using SQL Server, this should do for you.
create table #A(id int , cdr varchar(100))
insert into #A values(1,'10,20,30,40'),(2, '20,30,40,50'),(3,'30,40,50,60,70')
Declare #tA as table(id int , String varchar(10))
insert into #tA
SELECT id,
Split.a.value('.', 'VARCHAR(100)') AS String
FROM (SELECT [id],
CAST ('<M>' + REPLACE([cdr], ',', '</M><M>') + '</M>' AS XML) AS String
FROM #A) AS A CROSS APPLY String.nodes ('/M') AS Split(a);
delete from #tA where [String] = '30'
SELECT distinct id,
ISNULL(STUFF((SELECT ', ' + String
FROM #tA t
WHERE t.id = ta.id
FOR XML PATH('')
), 1, 1, ''), '') AS Str
into #tempA
FROM #tA ta
select * from #tempA
drop table #A, #tempA
UPDATE TableName
SET CDR = REPLACE(CDR, (SUBSTRING( CDR, LEN(CDR) - CHARINDEX(',',REVERSE(CDR)) + 2 , LEN(CDR))),0);
You should think about splitting up your comma separated list into a separate table. That way you can do other things in SQL. SQL is not the best with string manipulation and your queries are gonna get obscene and unruly.
table Users
user_id user_name job_list
1 Billy "1,2,3,4"
table Jobs
job_id job_desc
1 plumber
2 carpenter
3 electrician
4 programmer
If you do this you're gonna have some heartaches where a job goes away or something you're gonna have a lot of annoying cleanup like #jarlh suggests.
If you make a third table to hold the relationships user_id to job_id you will have a much better time if you need to do something like delete a job_id from existence. Of course this is all made up based on your limited question, but it should help you out.
table UserJobRelationship
relationship_id user_id job_id
1 1 1
2 1 2
3 1 3
4 1 4
Gives you much more flexibility and allows you to delete the most recent entry. You can simply just do max of relationship_id where user_id equals that user or you can do it for the whole table.

Finding max value for a column containing hierarchical decimals

I have a table where the column values are like '1.2.4.5', '3.11.0.6',
'3.9.3.14','1.4.5.6.7', N/A, etc.. I want to find the max of that particular column. However when i use this query i am not getting the max value.
(SELECT max (CASE WHEN mycolumn = 'N/A'
THEN '-1000'
ELSE mycolumn
END )
FROM mytable
WHERE column like 'abc')
I am getting 3.9.3.14 as max value instead of 3.11....
Can someone help me?
Those aren't really decimals - they're strings containing multiple dots, so it's unhelpful to think of them as being "decimals".
We can accomplish your query with a bit of manipulation. There is a type build into SQL Server that more naturally represents this type of structure - hierarchyid. If we convert your values to this type then we can find the MAX fairly easily:
declare #t table (val varchar(93) not null)
insert into #t(val) values
('1.2.4.5'),
('3.11.0.6'),
('3.9.3.14'),
('1.4.5.6.7')
select MAX(CONVERT(hierarchyid,'/' + REPLACE(val,'.','/') + '/')).ToString()
from #t
Result:
/3/11/0/6/
I leave the exercise of fully converting this string representation back into the original form as an exercise for the reader. Alternatively, I'd suggest that you may want to start storing your data using this datatype anyway.
MAX() on values stored as text performs an alphabetic sort.
Use FIRST_VALUE and HIERARCHYID:
SELECT DISTINCT FIRST_VALUE(t.mycolumn) OVER(
ORDER BY CONVERT(HIERARCHYID, '/' + REPLACE(NULLIF(t.mycolumn,'N/A'), '.', '/') + '/') DESC) AS [Max]
FROM #mytable t