Split string in T-SQL and inserting into parameter - sql-server

I need to split a string by delimiters |, then for every value obtained, I need to insert same in the name field like so:
INSERT INTO Monitoring (UserId, Name, DateCreated)
VALUES (#UserId, 'abc', getdate())
VALUES (#UserId, 'def', getdate()) etc...
Below is my code to split the string.
DECLARE #SplitStringTable TABLE (Value nvarchar(MAX) NOT NULL)
DECLARE #StringToSplit nvarchar(MAX) = 'abc|def|gh|ijj'
DECLARE #SplitEndPos int
DECLARE #SplitValue nvarchar(MAX)
DECLARE #SplitDelim nvarchar(1) = '|'
DECLARE #SplitStartPos int = 1
SET #SplitEndPos = CHARINDEX(#SplitDelim, #StringToSplit, #SplitStartPos)
WHILE #SplitEndPos > 0
BEGIN
SET #SplitValue = SUBSTRING(#StringToSplit, #SplitStartPos, (#SplitEndPos - #SplitStartPos))
INSERT #SplitStringTable (Value) VALUES (#SplitValue)
SET #SplitStartPos = #SplitEndPos + 1
SET #SplitEndPos = CHARINDEX(#SplitDelim, #StringToSplit, #SplitStartPos)
END
BEGIN TRANSACTION T1
DECLARE #i int = 0
WHILE #i < #SplitEndPos
BEGIN
INSERT INTO Monitoring (UserId, Name, DateCreated)
VALUES (#UserId, #Name, getdate())
SET #i = #i + 1
END
COMMIT TRANSACTION T1
Any help please, how shall I proceed?

There are many split/parsing functions out there.
Assume variables:
Declare #UserID int = 1
Declare #String varchar(max)='abc|def'
Insert Into Monitoring (UserId,Name,DateCreated)
Select UserID = #UserID
,Name = Key_Value
,DateCreated = GetDate()
From [dbo].[udf-Str-Parse](#String,'|')
The following would be inserted
UserID Name DateCreated
1 abc 2016-09-26 17:31:24.107
1 def 2016-09-26 17:31:24.107
The UDF if needed
CREATE FUNCTION [dbo].[udf-Str-Parse] (#String varchar(max),#Delimiter varchar(10))
Returns Table
As
Return
(
Select Key_PS = Row_Number() over (Order By (Select null))
,Key_Value = LTrim(RTrim(B.i.value('(./text())[1]', 'varchar(max)')))
From (Select x = Cast('<x>'+ Replace(#String,#Delimiter,'</x><x>')+'</x>' as xml).query('.')) as A
Cross Apply x.nodes('x') AS B(i)
);
EDIT
By the way, if you just run the parse function alone, you would get the following:
Declare #String varchar(max)='abc|def'
Select * From [dbo].[udf-Str-Parse](#String,'|')
-- Returns
Key_PS Key_Value
1 abc
2 def

Related

TSQL: multiple split string in one query

I have a string_split function which looks like below
CREATE FUNCTION [dbo].[String_Split](#String varchar(8000), #Delimiter char(1))
returns #temptable TABLE ([value] varchar(8000))
as
begin
declare #idx int
declare #slice varchar(8000)
select #idx = 1
if len(#String)<1 or #String is null return
while #idx!= 0
begin
set #idx = charindex(#Delimiter,#String)
if #idx!=0
set #slice = left(#String,#idx - 1)
else
set #slice = #String
if(len(#slice)>0)
insert into #temptable([value]) values(#slice)
set #String = right(#String,len(#String) - #idx)
if len(#String) = 0 break
end
return
end
I am now successfully able to split the string using the below code
declare #NameList nvarchar(100) = 'Hi,Hi1,Hi2';
SELECT * FROM string_split(#NameList,',')
but now I want to split multiple string using the same function like below
declare #NameList nvarchar(100) = 'Hi,Hi1,Hi2';
declare #DESCLIST nvarchar(100) = 'Hii,Hii1,Hii2';
I want to split these strings in different columns,
my expected output is
col 1 col 2
------------------
Hi |Hii
Hi1 |Hii1
Hi2 |Hii2
how can I achieve this?
You can join them on row-number.
SELECT
s1.value,
s2.value
FROM (
SELECT *,
rn = ROW_NUMBER() OVER (ORDER BY (SELECT NULL))
FROM STRING_SPLIT(#NameList, ',') s
) s1
JOIN (
SELECT *,
rn = ROW_NUMBER() OVER (ORDER BY (SELECT NULL))
FROM STRING_SPLIT(#DESCLIST, ',') s
) s2 ON s2.rn = s1.rn;
db<>fiddle
I strongly suggest you store multiple items in separate rows, rather than a comma-separated list. Consider using a table variable, temporary table or Table Valued Parameter.

How can I get a missing value from "where in ()" in T-SQL?

If I have a table with a column named "Ids" and another column named "clients" and I have the following data:
IDs Clients
----------------
1 A
2 B
3 C
4 D
I'm trying to get the IDs for multiple clients without writing a query for each one.
So I am using:
select ids
from table1
where clients in (A,B,E,C)
This returns
1,2,3
But I need to know that E is missing. So I really need
1,2,NULL,3
How can I accomplish this?
You can inline the values
declare #t table (id int, client char(1))
insert into #t values
(1, 'A'),
(2, 'B'),
(3, 'C'),
(4, 'D');
select *
from #t;
SELECT q.client, t.id
FROM ( values ('A'), ('B'), ('E') ) q(client)
left join #t t
on t.client = q.client;
Don't use plural for columns. A row is singular.
Insert your input to a table and proceed your query as below
declare #tbl table (ids int, clients varchar(10))
insert into #tbl values
(1,'A')
,(2,'B')
,(3,'C')
,(4,'D')
SELECT * FROM #tbl
declare #value table (Val varchar(10))
insert into #value values
('A')
,('B')
,('C')
,('E')
select ids,t1.Val
from #tbl t
RIGHT JOIN #value t1 on t1.Val = t.clients
Alertnate option.
declare #tbl table (ids int, clients varchar(10))
insert into #tbl values
(1,'A')
,(2,'B')
,(3,'C')
,(4,'D')
For SQL Server 2016 and above
Declare #var varchar(50) = 'A,B,C,E'
SELECT ids, t1.value
FROM #tbl t
RIGHT JOIN STRING_SPLIT(#var, ',') t1 on t1.value = t.clients
For lower than SQL Server 2016 use below query. You have to create strparse function. script given below
SELECT ids, t1.Keys
FROM #tbl t
RIGHT JOIN dbo.StrParse (',', #var) t1 on t1.Keys = t.clients
go
Create the function for parsing string to rows
CREATE FUNCTION [dbo].[StrParse]
(#delimiter CHAR(1),
#csv NTEXT)
RETURNS #tbl TABLE(Keys NVARCHAR(255))
AS
BEGIN
DECLARE #len INT
SET #len = Datalength(#csv)
IF NOT #len > 0
RETURN
DECLARE #l INT
DECLARE #m INT
SET #l = 0
SET #m = 0
DECLARE #s VARCHAR(255)
DECLARE #slen INT
WHILE #l <= #len
BEGIN
SET #l = #m + 1--current position
SET #m = Charindex(#delimiter,Substring(#csv,#l + 1,255))
IF #m <> 0
SET #m = #m + #l
--insert #tbl(keys) values(#m)
SELECT #slen = CASE
WHEN #m = 0 THEN 255
ELSE #m - #l
END
IF #slen > 0
BEGIN
SET #s = Substring(#csv,#l,#slen)
INSERT INTO #tbl
(Keys)
SELECT #s
END
SELECT #l = CASE
WHEN #m = 0 THEN #len + 1
ELSE #m + 1
END
END
RETURN
END

Add columns dynamically and Later Parse values in the respective columns

I have an SP which accepts the Inputtable as parameter, My Inputtable is as shown in the code
`create table inputTable ( id int,ItemQty varchar(100))
insert into inputTable(id, ItemQty) values(1,'a,b,c')
insert into inputTable(id, ItemQty) values(2,'x,y')
insert into inputTable(id, ItemQty) values(3,'l,m,n,o,p')
insert into inputTable(id, ItemQty) values(4,'a,b')
insert into inputTable(id, ItemQty) values(5,'m')`
and SP i have written is like below
`ALTER PROCEDURE [dbo].[Column_Dynamics] (#tablename varchar(50))
AS
BEGIN
-----
declare #maxcount as int
set #maxcount='select MAX(len(ITEMQTY) - len(replace(ITEMQTY, '','', '''')) +1) from '+#tablename
exec('select MAX(len(ITEMQTY) - len(replace(ITEMQTY, '','', '''')) +1) from '+#tablename)
print #maxcount
exec #maxcount
print #maxcount
declare #var varchar(100)
IF EXISTS(SELECT * FROM sys.columns WHERE object_id = Object_id(#tablename))
set #var='alter table '+ #tablename +' ADD column QTY1'
exec(#var)
select * from #tablename
select max(len(ItemQty))-max(len(replace(ItemQty, ',', ''))-1) from inputtable
END`
My table is :
step 1 ) I want to add the columns dynamically to inputtable like QTY1,QTY2,QTY3,QTY4,QTY5 because maximum count of ItemQty column is 5, by considering comma as delimiter as shown in figure1
**step 2) ** Parse values in the respective columns(by considering the delimiter comma (,).as shown in figure2
Later SP: I got till here, But Not getting the second step, that is update Parse values in the respective columns.
ALTER PROCEDURE dynamic_tbl (#tablename varchar(50))
AS
BEGIN
DECLARE #ColumnCount int
DECLARE #rowcount TABLE (Value int);
INSERT INTO #rowcount
EXEC('select MAX(len(ITEMQTY) - len(replace(ITEMQTY, '','', '''')) +1) from '+#tablename);
SELECT #ColumnCount = Value FROM #rowcount;
Declare #ColumnName nvarchar(10)='qty_'
Declare #count int =0
IF(#ColumnCount>0)
BEGIN
IF (EXISTS (SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'dbo' AND TABLE_NAME = 'dyn_tbl'))
BEGIN
DROP TABLE dyn_tbl
END
select * into dyn_tbl from inputtable
SET #count=#count +1;
WHile(#ColumnCount>=#count)
BEGIN
SET #ColumnName='qty_'+CONVERT(varchar(2),#count)
EXEC ('ALTER TABLE dyn_tbl ADD ['+#ColumnName +'] varchar(20)')
declare #myvar as varchar(max)
set #myvar='update '+#tablename+' set '+#ColumnName +' =itemQty'
--exec dynamic_tbl 'dyn_tbl'
--select * from dyn_tbl
--CAST('<A>'+REPLACE(ITEMQTY, ',', '</A><A>')+'</A>' AS XML)
print #myvar
exec(#myvar)
SET #count=#count +1;
END
END
----
END
Procedure to alter given table dynamically based on column length as you have asked
Alter PROCEDURE [dbo].[Column_Dynamics] (#tablename varchar(50))
AS
BEGIN
drop table ##temp
declare #query1 varchar(max)
exec ( '
create table ##temp (id int identity,columnsl varchar(100))
declare #maxcount as int
set #maxcount = (select MAX(len(ITEMQTY) - len(replace(ITEMQTY, '','', '''')) +1) from '+#tablename+')
declare #count int = 1
while (#count <= #maxcount)
begin
declare #colvar nvarchar(100)= ''QTY''
set #colvar = concat(#colvar,#count)
set #count = #count + 1
insert into ##temp select #colvar
end
')
declare #tempstart int = 1
declare #templast int = (select count(*) from ##temp)
declare #updatecol varchar(100) = ''
while (#tempstart <= #templast)
Begin
set #updatecol = (select columnsl from ##temp where id = #tempstart)
exec ('alter table '+#tablename+' Add '+#updatecol+' varchar(100) ')
set #tempstart = #tempstart + 1
end
End
output for inputTable:
id ItemQty QTY1 QTY2 QTY3 QTY4 QTY5
1 a,b,c NULL NULL NULL NULL NULL
2 x,y NULL NULL NULL NULL NULL
3 l,m,n,o,p NULL NULL NULL NULL NULL
4 a,b NULL NULL NULL NULL NULL
5 m NULL NULL NULL NULL NULL
may not be the best way but works.
edit
Altered above procedure to perform both actions, Please use below procedure
Alter PROCEDURE [dbo].[Column_Dynamics] (#tablename varchar(50))
AS
BEGIN
-- declare #tablename varchar(100) = 'inputTable'
drop table #temp if object_id('temp..#temp') is not null drop table #temp
declare #query1 varchar(max)
create table #temp (id int identity,columnsl varchar(100))
exec ( '
declare #maxcount as int
set #maxcount = (select MAX(len(ITEMQTY) - len(replace(ITEMQTY, '','', '''')) +1) from '+#tablename+')
declare #count int = 1
while (#count <= #maxcount)
begin
declare #colvar nvarchar(100)= ''QTY''
set #colvar = concat(#colvar,#count)
set #count = #count + 1
insert into #temp
select #colvar
end
')
declare #tempstart int = 1
declare #templast int = (select count(*) from #temp)
declare #updatecol varchar(100) = ''
declare #itemqty varchar(100)
while (#tempstart <= #templast)
Begin
set #updatecol = (select columnsl from #temp where id = #tempstart)
exec ('alter table '+#tablename+' Add '+#updatecol+' varchar(100) ')
set #tempstart = #tempstart + 1
end
declare #sysvar table (id int identity,cols varchar(100))
insert into #sysvar select sys.columns.name AS ColumnName FROM sys.columns JOIN sys.tables ON sys.columns.object_id = sys.tables.object_id WHERE sys.tables.name = 'inputTable'
declare #finvar table (id int identity,cols varchar(100))
insert into #finvar select cols from #sysvar where id not in (1,2)
declare #cat int = 1 declare #dog int = (select max(id) from inputTable)
while (#cat <= #dog)
begin
drop table #tab2
if object_id('temp..#tab2') is not null drop table #tab2
create table #tab2 (id int identity,fnvalues varchar(100))
set #itemqty = (select itemqty from inputTable where id = #cat)
insert into #tab2 select item from [dbo].[fnSplit](#itemQty,',')
declare #cn int = 1
declare #max int = (select max(id) from #tab2)
declare #sql nvarchar (1000);
while (#cn <= #max)
begin
declare #upcol varchar(100) = (select fnvalues from #tab2 where id = #cn)
declare #plscol varchar(100) = (select cols from #finvar where id = #cn)
set #sql = N'update '+#tablename+' set ' + #plscol + '= '''+#upcol+''' where id = '''+cast(#cat as varchar(10))+''' ';
select #sql
exec sp_executesql #sql;
set #cn = #cn + 1
end
set #cat = #cat + 1
End
End
output:
id ItemQty QTY1 QTY2 QTY3 QTY4 QTY5
1 a,b,c a b c NULL NULL
2 x,y x y NULL NULL NULL
3 l,m,n,o,p l m n o p
4 a,b a b NULL NULL NULL
5 m m NULL NULL NULL NULL
did not optimize the query but works fine.
However, if you have maximum Qty's are known which are in comma separated format then you could use xml node method to separate them into columns.QTY1...QTY5
SELECT DISTINCT ID, ITEMQTY,
a.value('/A[1]', 'VARCHAR(MAX)') as QTY1,
a.value('/A[2]', 'VARCHAR(MAX)') as QTY2,
a.value('/A[3]', 'VARCHAR(MAX)') as QTY3,
a.value('/A[4]', 'VARCHAR(MAX)') as QTY4,
a.value('/A[5]', 'VARCHAR(MAX)') as QTY5
FROM
(
SELECT ID, ITEMQTY,
CAST('<A>'+REPLACE(ITEMQTY, ',', '</A><A>')+'</A>' AS XML) AS ITEMQTY1
FROM inputTable
) A
CROSS APPLY ITEMQTY1.nodes('/A') AS split(a);
Result :
ID ITEMQTY QTY1 QTY2 QTY3 QTY4 QTY5
1 a,b,c a b c NULL NULL
2 x,y x y NULL NULL NULL
3 l,m,n,o,p l m n o p
4 a,b a b NULL NULL NULL
5 m m NULL NULL NULL NULL
Later, you could replace null by using coalesce() or isnull() function with ''
Use This
First Create a function
CREATE FUNCTION [dbo].[fn_split](
#str VARCHAR(MAX),
#delimiter CHAR(1)
)
RETURNS #returnTable TABLE (idx INT PRIMARY KEY IDENTITY, item VARCHAR(8000))
AS
BEGIN
DECLARE #pos INT
SELECT #str = #str + #delimiter
WHILE LEN(#str) > 0
BEGIN
SELECT #pos = CHARINDEX(#delimiter,#str)
IF #pos = 1
INSERT #returnTable (item)
VALUES (NULL)
ELSE
INSERT #returnTable (item)
VALUES (SUBSTRING(#str, 1, #pos-1))
SELECT #str = SUBSTRING(#str, #pos+1, LEN(#str)-#pos)
END
RETURN
END
GO
and use function like this
Declare #test TABLE (
ID VARCHAR(200),
Data VARCHAR(200)
)
insert into #test
(ID, Data)
Values
(1,'a,b,c')
insert into #test
(ID, Data )
values(2,'x,y')
insert into #test
(ID, Data )
values(3,'l,m,n,o,p')
insert into #test
(ID, Data )
values(4,'a,b')
insert into #test
(ID, Data )
values(5,'m')
select ID,data AS ItemQty,
ISNULL((select item from fn_split(Data,',') where idx in (1)),'') as QTY1 ,
ISNULL((select item from fn_split(Data,',') where idx in (2)),'') as QTY2,
ISNULL((select item from fn_split(Data,',') where idx in (3)),'') as QTY3,
ISNULL((select item from fn_split(Data,',') where idx in (4)),'') as QTY5 ,
ISNULL((select item from fn_split(Data,',') where idx in (5)),'') as QTY5
from #test
Output Same as your Image
instead of using
insert into #test
(ID, Data)
Values
(1,'a,b,c')
you can also assgin it like this
insert into #test
(ID, Data)
Values
(Select Column1, Column2 From YourTable)

How to get substring in SQL Server?

I have the next table, how can I get substring before and after dot(.) special character?
MyTable
------------------------------
Id Description
------------------------------
1 [Hugo].[date].[Subtotal]
2 [Juan].[date].[Subtotal]
3 [7/23/2013].[SubTotal]
4 [7/25/2013].[Total]
I am looking for the following result
MyResultTable
------------------------
MyTableId Description depth
-----------------------
1 [Hugo] 1
1 [date] 2
1 [Subtotal] 3
2 [Juan] 1
2 [date] 2
2 [Subtotal] 3
3 [7/23/2013] 1
3 [SubTotal] 2
4 [7/25/2013] 1
4 [Total] 2
I want to separate the words after a dot(.) and list the words as the following table
How can I solve it?
You will want to split the data based on the .. You can use a recursive CTE to split the data and return the depth:
;with cte (id, DescriptionItem, Description, depth) as
(
select id,
cast(left(Description, charindex('.',Description+'.')-1) as varchar(50)) DescriptionItem,
stuff(Description, 1, charindex('.',Description+'.'), '') Description,
1 as depth
from MyTable
union all
select id,
cast(left(Description, charindex('.',Description+'.')-1) as varchar(50)) DescriptionItem,
stuff(Description, 1, charindex('.',Description+'.'), '') Description,
depth+1
from cte
where Description > ''
)
select id, DescriptionItem, depth
from cte
order by id, depth;
See SQL Fiddle with Demo
Or you can use a UDF function that splits the data:
create FUNCTION [dbo].[Split](#String varchar(MAX), #Delimiter char(1))
returns #temptable TABLE (items varchar(MAX), depth int)
as
begin
declare #idx int
declare #slice varchar(8000)
declare #depth int = 1
select #idx = 1
if len(#String)<1 or #String is null return
while #idx!= 0
begin
set #idx = charindex(#Delimiter,#String)
if #idx!=0
set #slice = left(#String,#idx - 1)
else
set #slice = #String
if(len(#slice)>0)
insert into #temptable(Items, depth) values(#slice, #depth)
set #String = right(#String,len(#String) - #idx)
set #depth = #depth +1
if len(#String) = 0 break
end
return
end;
Then when you call the function, you will use CROSS APPLY similar to this:
select t.id, c.items description,
c.depth
from mytable t
cross apply dbo.split(t.description, '.') c
order by t.id, c.depth;
See SQL Fiddle with Demo
USE tempdb;
GO
IF OBJECT_ID('dbo.csv_split','U') IS NOT NULL DROP TABLE dbo.csv_split;
CREATE TABLE dbo.csv_split
(
Id INT NOT NULL PRIMARY KEY
,Description VARCHAR(100)
)
INSERT INTO dbo.csv_split(Id,Description)
VALUES
(1,'[Hugo].[date].[Subtotal]')
,(2,'[Juan].[date].[Subtotal]')
,(3,'[7/23/2013].[SubTotal]')
,(4,'[7/25/2013].[Total]');
WITH cte_xml AS
(
Select csv.Id
,CONVERT(XML,'<desc>'
+ REPLACE(csv.Description,'.','</desc><desc>')
+ '</desc>') AS xml_desc
From dbo.csv_split csv
)
,cte_shred_xml AS
(
Select t.Id
,xml_desc_nodes.value('(.)','varchar(50)') AS Description
,ROW_NUMBER() OVER(PARTITION BY t.Id ORDER BY t.Id ) AS Depth
From cte_xml t
CROSS APPLY t.xml_desc.nodes('/desc') AS t2(xml_desc_nodes)
)
Select *
From cte_shred_xml
Here is a simple example. I created your table as #test and used both a cursor and a loop within the cursor.
DECLARE #test TABLE ( id INT, NAME VARCHAR(MAX) )
INSERT #test
VALUES ( 1, '[Hugo].[date].[Subtotal]' )
INSERT #test
VALUES ( 2, '[Juan].[date].[Subtotal]' )
INSERT #test
VALUES ( 3, '[7/23/2013].[SubTotal]' )
INSERT #test
VALUES ( 4, '[7/25/2013].[Total]' )
DECLARE #id INT ,
#name VARCHAR(MAX)
DECLARE #values TABLE
(
MyTableId INT ,
Description VARCHAR(MAX) ,
Depth INT
)
DECLARE #v VARCHAR(2000) ,
#i INT ,
#depth INT
DECLARE #MyTableList CURSOR
SET
#MyTableList = CURSOR FOR SELECT id, name FROM #test
OPEN #MyTableList
FETCH NEXT FROM #MyTableList INTO #id, #name
WHILE ##FETCH_STATUS = 0
BEGIN
SET #depth = 1
SET #i = PATINDEX('%.%', #name)
WHILE #i > 0
BEGIN
INSERT #values
VALUES ( #id, SUBSTRING(#name, 1, #i - 1), #depth )
SET #name = SUBSTRING(#name, #i + 1, LEN(#name) - #i)
SET #i = PATINDEX('%.%', #name)
SET #depth = #depth + 1
END
INSERT #values
VALUES ( #id, #name, #depth )
FETCH NEXT FROM #MyTableList INTO #id, #name
END
SELECT MyTableId ,
Description ,
Depth
FROM #values
You output should look like this.
MyTableId Description Depth
1 [Hugo] 1
1 [date] 2
1 [Subtotal] 3
2 [Juan] 1
2 [date] 2
2 [Subtotal] 3
3 [7/23/2013] 1
3 [SubTotal] 2
4 [7/25/2013] 1
4 [Total] 2

SQL - Determine the most frequently occuring words within a column

Is there an easy way of determining the most frequently occuring word in a column/field using T-SQL or VBA?
I am working on a fuzzy matching system for two given recordsets and would like to produce a matching string where the most frequently occuring words are removed. As the data is from a customer relations management database terms like "limited", "ltd", "plc" and "CORPORATION" would be removed.
Written for sql-server 2005+
Function to split:
create function f_split
(
#a varchar(max),
#delimiter varchar(20)
)
RETURNS #t TABLE(substr varchar(200))
as
begin
set #a = #a + #delimiter
;with a as
(
select cast(1 as bigint) f1, charindex(#delimiter, #a) f2
where len(#a) > 0
union all
select f2 + (len(#delimiter)) + 1, charindex(#delimiter, #a, f2+1)
from a
where f2 > 0
)
insert #t
select substring(#a, f1, f2 - f1) from a
where f1 < f2
return
end
go
Query:
--testdata
declare #table table(name varchar(50))
insert #table values('bla bla bla ltd')
insert #table values('bla plc ltd')
insert #table values('more text CORPORATION')
declare #matchlist table(name varchar(50), replacement varchar(50))
insert #matchlist values('ltd', 'limited')
insert #matchlist values('plc', 'limited')
insert #matchlist values('CORPORATION', 'limited')
--query
select coalesce(m.replacement, a.substr) name, count(*) count from #table p
cross apply
(
select substr from
dbo.f_split(p.name, ' ')
) a
left join
#matchlist m
on a.substr = m.name
group by coalesce(m.replacement, a.substr)
order by 2 desc
Result:
name count
---- -----
bla 4
limited 4
more 1
text 1
Hope this will be useful to you.
create table sometable
( id integer not null primary key identity
, mYWords text not null
);
insert into sometable (mYWords)
values ('a word that appears maximum number of times in a column')
insert into sometable (mYWords)
values ('Is it possible to get words from text columns in a sql server database')
insert into sometable (mYWords)
values ('This could solve my problem if reffered column contain only single word')
insert into sometable (mYWords)
values ('that''s going to require that you split out every word in the column individually')
insert into sometable (mYWords)
values ('the query will definitely not be easy to write')
insert into sometable (mYWords)
values ('Please read the sticky at the top of the board')
insert into sometable (mYWords)
values ('The physical order of data in a database has no meaning')
GO
CREATE TABLE WordList (
Word varchar(256)
, WordId int IDENTITY(1,1)
, Add_Dt datetime DEFAULT (GetDate()))
GO
CREATE UNIQUE INDEX UnqueWords_PK ON WordList(Word)
GO
CREATE PROC isp_INS_WORD_LIST
AS
BEGIN
SET NOCOUNT ON
DECLARE #Words INT, #Pos INT, #x Int, #str varchar(256)
, #word varchar(256), #start int, #end int, #exitstart int
SELECT #Words = 0, #Pos = 1, #x = -1, #Word = '', #start = 1
DECLARE Cur1 CURSOR FOR SELECT mYWords FROM sometable
OPEN Cur1
FETCH NEXT FROM Cur1 INTO #str
WHILE ##FETCH_STATUS = 0
BEGIN
WHILE (#x <> 0)
BEGIN
SET #x = CHARINDEX(' ', #str, #Pos)
IF #x <> 0
BEGIN
SET #end = #x - #start
SET #word = SUBSTRING(#str,#start,#end)
IF NOT EXISTS (SELECT * FROM WordList WHERE Word = #Word)
INSERT INTO WordList(Word) SELECT #word
-- SELECT #Word, ##ROWCOUNT,##ERROR
-- SELECT #x, #Word, #start, #end, #str
SET #exitstart = #start + #end + 1
SET #Pos = #x + 1
SET #start = #x + 1
SET #Words = #Words + 1
END
IF #x = 0
BEGIN
SET #word = SUBSTRING(#str,#exitstart,LEN(#str)-#exitstart+1)
IF NOT EXISTS (SELECT * FROM WordList WHERE Word = #Word)
INSERT INTO WordList(Word) SELECT #word
-- SELECT #Word, ##ROWCOUNT,##ERROR
-- SELECT #x, #Word, #exitstart, LEN(#str)-#exitstart, #str
END
END
FETCH NEXT FROM Cur1 INTO #str
SELECT #Words = 0, #Pos = 1, #x = -1, #Word = '', #start = 1
END
CLOSE Cur1
DEALLOCATE Cur1
SET NOCOUNT OFF
RETURN #Words
END
GO
EXEC isp_INS_WORD_LIST
GO
SELECT * FROM WordList ORDER BY Word
GO
DROP PROC isp_INS_WORD_LIST
DROP TABLE WordList, sometable
GO

Resources