how to split one value from sql?
EX: column SQL
Now, I want split to
Code:
declare #ND nvarchar(max)= N'AA (AA11) [37100]'
select substring(#ND,1,patindex('%[0-9]%',#ND)-2) as Name
,substring(#ND,patindex('%[0-9]%',#ND),len(#ND)) as Number
Declare #t table (fullname varchar(50))
insert into #t values ('AA [1111]')
insert into #t values ('BB(15CC) [2222]')
select
fullname,
substring(fullname,1,CHARINDEX('[',fullname)-1) Name,
replace(substring(fullname,CHARINDEX('[',fullname)+1,len(fullname)),']','') as number
from #t
In your sample data, the last 6 characters are always square braces with the number. If this is always the case, you can use simpler logic:
select left(fullname, len(fullname) - 7),
left(right(fullname, 5), 4)
from #t;
Here is a db<>fiddle.
For a more general case, I would also want to handle the situation where there is no [ in the string without generating an error:
select left(fullname, charindex('[', fullname + '[') - 1),
replace(stuff(fullname, 1, charindex('[', fullname + '['), ''), ']', '')
from #t;
Here is another db<>fiddle.
You can do that by using CHARINDEX(), REPLACE(), LEN() and SUBSTRING() functions as
SELECT Str FullName,
REPLACE(Str, SUBSTRING(Str, CHARINDEX('[', Str), CHARINDEX(']', Str)), '') Name,
SUBSTRING(Str, CHARINDEX('[', Str) + 1, LEN(Str) - CHARINDEX('[', Str)-1) Number
FROM (VALUES('BBB(15CC)[222]'), ('AA[1111]')) T(Str);
OR
;WITH CTE AS
(
SELECT Str FullName,
LEFT(Str, CHARINDEX('[', Str) -1) Name
FROM (VALUES('BBB(15CC)[222]'), ('AA[1111]')) T(Str)
)
SELECT FullName,
Name,
REPLACE(REPLACE(FullName, Name + '[', ''), ']', '') Number
FROM CTE;
Returns:
+----------------+-----------+--------+
| FullName | Name | Number |
+----------------+-----------+--------+
| BBB(15CC)[222] | BBB(15CC) | 222 |
| AA[1111] | AA | 1111 |
+----------------+-----------+--------+
Using Xml conversion we can get the expected result
Declare #t table (fullname varchar(50))
insert into #t values ('AA [1111]')
insert into #t values ('BB(15CC) [2222]')
SELECT DISTINCT Fullname,
Split.a.value('/S[1]','nvarchar(100)') AS Name,
Split.a.value('/S[2]','nvarchar(100)') AS Number
FROM
(
SELECT Fullname,
CAST('<S>'+REPLACE(REPLACE(REPLACE(Fullname,' ','</S><S>')+'</S>','[',''),']','') AS XML ) AS FullnameData
FROM #t
)AS A
CROSS APPLY FullnameData.nodes('S') AS Split(a)
Result
Fullname Name Number
----------------------------------------
AA [1111] AA 1111
BB(15CC) [2222] BB(15CC) 2222
Related
How can I replace 'a' to blank?
`Name` `ID`
----------------------------------
`b,c,d,e,abb,a` `1`
`b,c,d,a,e,abb` `2`
`a,b,c,d,a,e,abb` `3`
One way to do it would be to add a , to the beginning and end of each Name, then replace every occurence of ',a,' with ',', then trim the result of the ,:
update table_name
set Name = trim(',' from replace(concat(',', Name, ','), ',a,', ','));
Fiddle
Or if you just want to do a select without changing the rows:
select trim(',' from replace(concat(',', Name, ','), ',a,', ',')) as Name, ID
from table_name;
To address #Iptr's comment, if there can be consecutive a such as a, a, ..., you could use STRING_SPLIT to get rows from comma-separated values, then filter out where the value is a, then STRING_AGG and group by to get the comma separated values back:
select ID, STRING_AGG(u.Value, ',') as Name
from table_name
cross apply STRING_SPLIT (Name, ',') u
where Value <> 'a'
group by ID
Fiddle
Here is a solution based on tokenization via XML/XQuery.
It will work starting from SQL Server 2012 onwards.
Steps:
We are tokenizing a string of tokens via XML.
XQuery FLWOR expression is filtering out the 'a' token.
Reverting it back to a string of tokens.
SQL
-- DDL and sample data population, start
DECLARE #tbl TABLE (ID INT IDENTITY PRIMARY KEY, tokens VARCHAR(1000));
INSERT INTO #tbl (tokens) VALUES
('b,c,d,e,abb,a'),
('b,c,d,a,e,abb'),
('a,b,c,d,a,e,abb');
-- DDL and sample data population, end
DECLARE #separator CHAR(1) = ',';
SELECT t.*
, REPLACE(c.query('
for $x in /root/r/text()
return if ($x = "a") then ()
else data($x)
').value('.', 'VARCHAR(MAX)'), SPACE(1), #separator) AS Result
FROM #tbl AS t
CROSS APPLY (SELECT TRY_CAST('<root><r><![CDATA[' +
REPLACE(tokens, #separator, ']]></r><r><![CDATA[') +
']]></r></root>' AS XML)) AS t1(c);
Output
+----+-----------------+-------------+
| ID | tokens | Result |
+----+-----------------+-------------+
| 1 | b,c,d,e,abb,a | b,c,d,e,abb |
| 2 | b,c,d,a,e,abb | b,c,d,e,abb |
| 3 | a,b,c,d,a,e,abb | b,c,d,e,abb |
+----+-----------------+-------------+
Try as follow:
select Replace(name, N'a', N'') as RepName , ID from yourTable
Try this.
SELECT ID,Name, REPLACE(Name, 'a', ' ')
FROM tableName;
CREATE TABLE testcheck
(
id int,
colname nvarchar(255)
)
INSERT INTO testcheck (id, colname)
VALUES (1, 'xxx xxxxx (xx11111) | yyyy yyyyyy yyyyyyyy (yy1111)')
SELECT
SUBSTRING(RIGHT(Colname, LEN(Colname) - CHARINDEX('|', Colname)),
CHARINDEX('(', RIGHT(Colname, LEN(Colname) - CHARINDEX('|', Colname))) + 1,
CHARINDEX(')', Colname) - CHARINDEX('(', RIGHT(Colname, LEN(Colname) - CHARINDEX('|', Colname))) - 1) Colname
FROM
dbo.testcheck
My value is 'xxx xxxxx (xx11111) | yyyy yyyyyy yyyyyyyy (yy1111)' not sure why I get this error:
Invalid length parameter passed to the LEFT or SUBSTRING function
I want to extract text between brackets my complete code is as below
select case when LEN(colname)=0 then '' else case when SUBSTRING(Colname,CHARINDEX('(',Colname)+1,CHARINDEX(')',Colname)-CHARINDEX('(',Colname)-1)=
SUBSTRING(RIGHT(Colname,LEN(Colname)-CHARINDEX('|',Colname)),CHARINDEX('(',RIGHT(Colname,LEN(Colname)-CHARINDEX('|',Colname)))+1,CHARINDEX(')',Colname)-CHARINDEX('(',RIGHT(Colname,LEN(Colname)-CHARINDEX('|',Colname)))-1)
then SUBSTRING(Colname,CHARINDEX('(',Colname)+1,CHARINDEX(')',Colname)-CHARINDEX('(',Colname)-1)
else CONCAT(SUBSTRING(Colname,CHARINDEX('(',Colname)+1,CHARINDEX(')',Colname)-CHARINDEX('(',Colname)-1),',',SUBSTRING(RIGHT(Colname,LEN(Colname)-CHARINDEX('|',Colname)),CHARINDEX('(',RIGHT(Colname,LEN(Colname)-CHARINDEX('|',Colname)))+1,CHARINDEX(')',RIGHT(Colname,LEN(Colname)-CHARINDEX('|',Colname)))-CHARINDEX('(',RIGHT(Colname,LEN(Colname)-CHARINDEX('|',Colname)))-1)) end
END
from dbo.testcheck
This works for most values but doesnt work for few values
I usually handle this just by appending
SUBSTRING(RIGHT(Colname, LEN(Colname) - CHARINDEX('|', Colname || '|')),
CHARINDEX('(', RIGHT(Colname, LEN(Colname) - CHARINDEX('|', Colname || '|'))) + 1,
CHARINDEX(')', Colname) - CHARINDEX('(', RIGHT(Colname, LEN(Colname) - CHARINDEX('|', Colname || '|'))) - 1) Colname
You haven't specified what the code is supposed to be doing. But this should at least answer your question and eliminate the error.
Please try the following solutions.
SQL #1
It is for SQL Server 2017 onwards.
-- DDL and sample data population, start
DECLARE #tbl TABLE (id INT IDENTITY PRIMARY KEY, tokens NVARCHAR(255));
INSERT INTO #tbl (tokens) VALUES
('xxx xxxxx (xx11111) | yyyy yyyyyy yyyyyyyy (yy1111)');
-- DDL and sample data population, end
WITH rs AS
(
SELECT ID, TRIM([value]) AS [row]
FROM #tbl
CROSS APPLY STRING_SPLIT(tokens, '|')
)
SELECT ID, TRIM('()' FROM value) AS Result
FROM rs
CROSS APPLY STRING_SPLIT(row, SPACE(1))
WHERE LEFT(value,1) = '(';
SQL #2
It is for SQL Server 2012 onwards.
;WITH rs as
(
SELECT *
FROM #tbl
CROSS APPLY (SELECT TRY_CAST('<root><r><![CDATA[' +
REPLACE(tokens, SPACE(1), ']]></r><r><![CDATA[') +
']]></r></root>' AS XML)) AS t1(c)
)
SELECT ID --, c
, SUBSTRING(token, 2, LEN(token) - 2) AS Result
FROM rs
CROSS APPLY c.nodes('/root/r[substring(./text()[1],1,1)="("]/text()') AS t2(x)
CROSS APPLY (VALUES (x.value('.', 'VARCHAR(20)'))) AS t3(token);
Output
+----+---------+
| ID | Result |
+----+---------+
| 1 | xx11111 |
| 1 | yy1111 |
+----+---------+
I'm trying to count how many words there are in a string in SQL.
Select ("Hello To Oracle") from dual;
I want to show the number of words. In the given example it would be 3 words though there could be more than one space between words.
You can use something similar to this. This gets the length of the string, then substracts the length of the string with the spaces removed. By then adding the number one to that should give you the number of words:
Select length(yourCol) - length(replace(yourcol, ' ', '')) + 1 NumbofWords
from yourtable
See SQL Fiddle with Demo
If you use the following data:
CREATE TABLE yourtable
(yourCol varchar2(15))
;
INSERT ALL
INTO yourtable (yourCol)
VALUES ('Hello To Oracle')
INTO yourtable (yourCol)
VALUES ('oneword')
INTO yourtable (yourCol)
VALUES ('two words')
SELECT * FROM dual
;
And the query:
Select yourcol,
length(yourCol) - length(replace(yourcol, ' ', '')) + 1 NumbofWords
from yourtable
The result is:
| YOURCOL | NUMBOFWORDS |
---------------------------------
| Hello To Oracle | 3 |
| oneword | 1 |
| two words | 2 |
Since you're using Oracle 11g it's even simpler-
select regexp_count(your_column, '[^ ]+') from your_table
Here is a sqlfiddle demo
If your requirement is to remove multiple spaces too, try this:
Select length('500 text Oracle Parkway Redwood Shores CA') - length(REGEXP_REPLACE('500 text Oracle Parkway Redwood Shores CA',
'( ){1,}', '')) NumbofWords
from dual;
Since I have used the dual table you can test this directly in your own development environment.
DECLARE #List NVARCHAR(MAX) = ' ab a
x'; /*Your column/Param*/
DECLARE #Delimiter NVARCHAR(255) = ' ';/*space*/
DECLARE #WordsTable TABLE (Data VARCHAR(1000));
/*convert by XML the string to table*/
INSERT INTO #WordsTable(Data)
SELECT Data = y.i.value('(./text())[1]', 'VARCHAR(1000)')
FROM
(
SELECT x = CONVERT(XML, '<i>'
+ REPLACE(#List, #Delimiter, '</i><i>')
+ '</i>').query('.')
) AS a CROSS APPLY x.nodes('i') AS y(i)
/*Your total words*/
select count(*) NumberOfWords
from #WordsTable
where Data is not null;
/*words list*/
select *
from #WordsTable
where Data is not null
/from this Logic you can continue alon/
I have so many long database so I used seq_no in commas separate using more than one sequence store in single column but now I want all sequence in a single column so I am confused how to create this sql result for this.
For example:
TABLE STRUCTURE
SR_NO IS INT ,
SEQ_NO IS VARCHAR(MAX)
SR_NO SEQ_NO
---------------------------------
1 1839073,
2 1850097,1850098,
3 1850099,1850100,1850110
I need to get this result:
SEQ_NO
--------------
1839073
1850097
1850098
1850099
1850100
1850110
Thanks!
declare #t table(Id int,seq varchar(100))
insert into #t (Id,seq) values (1,'1839073,'),(2,'1839073,1850098,'),(3,'1850099,1850100,1850110 ')
;With Cte as (
SELECT A.Id,
Split.a.value('.', 'VARCHAR(100)') AS Seq
FROM
(
SELECT Id,
CAST ('<M>' + REPLACE(seq, ',', '</M><M>') + '</M>' AS XML) AS Data
FROM #t
) AS A CROSS APPLY Data.nodes ('/M') AS Split(a) )
Select ID,Seq from Cte Where Seq > ''
Try splitting it with XML
SELECT SR_NO, t.c.value('.', 'VARCHAR(2000)') COL1
FROM (
SELECT SR_NO, x = CAST('<t>' +
REPLACE(SEQ_NO, ',', '</t><t>') + '</t>' AS XML)
FROM
(values(1,'1839073'),(2, '1850097,1850098'),
(3, '1850099,1850100,1850110')) y(SR_NO, SEQ_NO)
) a
CROSS APPLY x.nodes('/t') t(c)
Result:
SR_NO COL1
1 1839073
2 1850097
2 1850098
3 1850099
3 1850100
3 1850110
You can replace this with your table:
(values (1,'1839073'),(2, '1850097,1850098'),
(3, '1850099,1850100,1850110')) y(SR_NO, SEQ_NO)
This should do it: (Replace YourTableName with your table name)
;WITH CTE(NEW_SEQ_NO, SEQ_NO) as (
SELECT LEFT(SEQ_NO, CHARINDEX(',',SEQ_NO + ',') -1),
STUFF(SEQ_NO, 1, CHARINDEX(',',SEQ_NO + ','), '')
FROM YourTableName
WHERE SEQ_NO <> '' AND SEQ_NO IS NOT NULL
UNION all
SELECT LEFT(SEQ_NO, CHARINDEX(',',SEQ_NO + ',') -1),
STUFF(SEQ_NO, 1, CHARINDEX(',',SEQ_NO + ','), '')
FROM CTE
WHERE SEQ_NO <> '' AND SEQ_NO IS NOT NULL
)
SELECT NEW_SEQ_NO from CTE ORDER BY NEW_SEQ_NO
You can check this topic for more information:
Turning a Comma Separated string into individual rows
I have written the following query after referring Turning a Comma Separated string into individual rows
It will work for you
create table STRUCTURE(SR_NO int, SEQ_NO varchar(max))
insert STRUCTURE select 1, '1839073,'
insert STRUCTURE select 2, '1850097,1850098,'
insert STRUCTURE select 3, '1850099,1850100,1850110'
;with tmp(SR_NO, DataItem, SEQ_NO) as (
select SR_NO, LEFT(SEQ_NO, CHARINDEX(',',SEQ_NO+',')-1),
STUFF(SEQ_NO, 1, CHARINDEX(',',SEQ_NO+','), '')
from STRUCTURE
union all
select SR_NO, LEFT(SEQ_NO, CHARINDEX(',',SEQ_NO+',')-1),
STUFF(SEQ_NO, 1, CHARINDEX(',',SEQ_NO+','), '')
from tmp
where SEQ_NO > ''
)
Select DataItem as SEQ_NO from tmp order by SEQ_NO;
I'm trying to count how many words there are in a string in SQL.
Select ("Hello To Oracle") from dual;
I want to show the number of words. In the given example it would be 3 words though there could be more than one space between words.
You can use something similar to this. This gets the length of the string, then substracts the length of the string with the spaces removed. By then adding the number one to that should give you the number of words:
Select length(yourCol) - length(replace(yourcol, ' ', '')) + 1 NumbofWords
from yourtable
See SQL Fiddle with Demo
If you use the following data:
CREATE TABLE yourtable
(yourCol varchar2(15))
;
INSERT ALL
INTO yourtable (yourCol)
VALUES ('Hello To Oracle')
INTO yourtable (yourCol)
VALUES ('oneword')
INTO yourtable (yourCol)
VALUES ('two words')
SELECT * FROM dual
;
And the query:
Select yourcol,
length(yourCol) - length(replace(yourcol, ' ', '')) + 1 NumbofWords
from yourtable
The result is:
| YOURCOL | NUMBOFWORDS |
---------------------------------
| Hello To Oracle | 3 |
| oneword | 1 |
| two words | 2 |
Since you're using Oracle 11g it's even simpler-
select regexp_count(your_column, '[^ ]+') from your_table
Here is a sqlfiddle demo
If your requirement is to remove multiple spaces too, try this:
Select length('500 text Oracle Parkway Redwood Shores CA') - length(REGEXP_REPLACE('500 text Oracle Parkway Redwood Shores CA',
'( ){1,}', '')) NumbofWords
from dual;
Since I have used the dual table you can test this directly in your own development environment.
DECLARE #List NVARCHAR(MAX) = ' ab a
x'; /*Your column/Param*/
DECLARE #Delimiter NVARCHAR(255) = ' ';/*space*/
DECLARE #WordsTable TABLE (Data VARCHAR(1000));
/*convert by XML the string to table*/
INSERT INTO #WordsTable(Data)
SELECT Data = y.i.value('(./text())[1]', 'VARCHAR(1000)')
FROM
(
SELECT x = CONVERT(XML, '<i>'
+ REPLACE(#List, #Delimiter, '</i><i>')
+ '</i>').query('.')
) AS a CROSS APPLY x.nodes('i') AS y(i)
/*Your total words*/
select count(*) NumberOfWords
from #WordsTable
where Data is not null;
/*words list*/
select *
from #WordsTable
where Data is not null
/from this Logic you can continue alon/