FREE TEXT SQL extract from fullname - sql-server

Need help with extracting the firstname, middlename and lastname from a
freetext fullname. How to extract them out with all these formats?
Need to figure out how to handle format 2,5,9,7
--fullname sample data
DECLARE #name TABLE
(fullname VARCHAR(100))
INSERT INTO #name SELECT
'Malone,Susan M' UNION ALL SELECT --1
'Conn,Chris G' UNION ALL SELECT --2
'Van Pess,Wen B' UNION ALL SELECT --3
'DESHPANDE, ANN W.' UNION ALL SELECT --4
'Asif,LEE' UNION ALL SELECT --5
'CERVANTES MANDY'UNION ALL SELECT --6
'Bill, Dave' UNION ALL SELECT --7
'SMITH,ANN M' UNION ALL SELECT --8
'BHULLER, MATT' UNION ALL SELECT --9
'KIM (DAUM), GAIL' UNION ALL SELECT --10
'John.Mills'--11
DECLARE #DELIMITER1 varchar(5), #DELIMITER2 varchar(5), #DELIMITER3
varchar(5),#MAX_LENGTH int
SET #DELIMITER1 = ','
SET #DELIMITER2 = ' '
SET #MAX_LENGTH = 50
--LastName
SELECT fullname,
case when
CHARINDEX(#DELIMITER2, fullname) >=1
then replace(SUBSTRING(fullname, 1, CHARINDEX(#DELIMITER2, fullname)
),',','')--replace to empty string if contains a ","
when
CHARINDEX(#DELIMITER2, fullname) =0
then replace(SUBSTRING(fullname, 1, CHARINDEX(#DELIMITER1, fullname)
),',','')--replace to empty string if contains a ","
else null
end as Lastname,
--Middle Name
CASE
-- Middle fullname follows two-fullname first fullnames like Mary Ann
WHEN LEN(SUBSTRING(fullname, CHARINDEX(#DELIMITER1,fullname)+
2,#MAX_LENGTH)) - LEN(REPLACE(SUBSTRING(fullname,
CHARINDEX(#DELIMITER1,fullname)+ 2,#MAX_LENGTH), #DELIMITER2, '')) > 0
--when len is greater than 0
THEN SUBSTRING(fullname, LEN(fullname) - CHARINDEX(#DELIMITER2,
REVERSE(fullname))+2, #MAX_LENGTH)
ELSE NULL
END AS Middlefullname,
--First Name
CASE
-- Count the number of #DELIMITER2. Choose the string between the
WHEN LEN(SUBSTRING(fullname, CHARINDEX(#DELIMITER1,fullname)+
2,#MAX_LENGTH)) - LEN(REPLACE(SUBSTRING(fullname,
CHARINDEX(#DELIMITER1,fullname)+ 2,#MAX_LENGTH), #DELIMITER2, '')) > 0 --
--when len is greater than 0
Then replace(ltrim(SUBSTRING(fullname, CHARINDEX(#DELIMITER1,fullname)+
1,
---need help here
(LEN(SUBSTRING(fullname, CHARINDEX(#DELIMITER1,fullname)+ 2,#MAX_LENGTH))-
LEN(SUBSTRING(fullname, LEN(fullname) - CHARINDEX(#DELIMITER2,
REVERSE(fullname))+2, #MAX_LENGTH))))),'-','') --replace the "-" to empty
string
ELSE ltrim(SUBSTRING(fullname,CHARINDEX(#DELIMITER1,fullname)+
1,#MAX_LENGTH))--trimmed leading spaces
END AS Firstname
FROM #name
order by fullname

First logic to concatenate the "name parts" with dots. Note my comments.
--fullname sample data
DECLARE #name TABLE
(nameid int identity, fullname VARCHAR(100))
INSERT INTO #name SELECT
'Malone,Susan M' UNION ALL SELECT --1
'Conn,Chris G' UNION ALL SELECT --2
'Van Pess,Wen B' UNION ALL SELECT --3
'DESHPANDE, ANN W.' UNION ALL SELECT --4
'Asif,LEE' UNION ALL SELECT --5
'CERVANTES MANDY'UNION ALL SELECT --6
'Bill, Dave' UNION ALL SELECT --7
'SMITH,ANN M' UNION ALL SELECT --8
'BHULLER, MATT' UNION ALL SELECT --9
'KIM (DAUM), GAIL' UNION ALL SELECT --10
'John.Mills';--11
select original = fullname, prepped = dotted.fn, total.spaces
from #name
cross apply (values (patindex('%(%),%',fullname),fullname)) prep1(x,fn) -- check for parentheses:
cross apply (values ( -- remove parentheses if they exist, replace commas w/ dots, dots w/ spaces:
case
when prep1.x > 1 then substring(fn,1,x-1) + substring(fn,charindex(',',fn,x)+1,8000)
else replace(replace(fn, ',', '.'),'.',' ')
end)) prep(fn)
cross apply (values (replace(rtrim(ltrim(replace(prep.fn,' ',' '))),' ',' '))) clean(fn)
cross apply (values (len(clean.fn)-len(replace(clean.fn,' ','')))) total(spaces) -- count spaces
cross apply (values (replace(clean.fn, ' ','.'))) dotted(fn); -- replace spaces with dots
This returns
original prepped spaces
------------------------ -------------------- -------
Malone,Susan M Malone.Susan.M 2
Conn,Chris G Conn.Chris.G 2
Van Pess,Wen B Van.Pess.Wen.B 3
DESHPANDE, ANN W. DESHPANDE.ANN.W 2
Asif,LEE Asif.LEE 1
CERVANTES MANDY CERVANTES.MANDY 1
Bill, Dave Bill.Dave 1
SMITH,ANN M SMITH.ANN.M 2
BHULLER, MATT BHULLER.MATT 1
KIM (DAUM), GAIL KIM.GAIL 1
John.Mills John.Mills 1
The rest can be done using parsename like so:
--fullname sample data
DECLARE #name TABLE
(nameid int identity, fullname VARCHAR(100))
INSERT INTO #name SELECT
'Malone,Susan M' UNION ALL SELECT --1
'Conn,Chris G' UNION ALL SELECT --2
'Van Pess,Wen B' UNION ALL SELECT --3
'DESHPANDE, ANN W.' UNION ALL SELECT --4
'Asif,LEE' UNION ALL SELECT --5
'CERVANTES MANDY'UNION ALL SELECT --6
'Bill, Dave' UNION ALL SELECT --7
'SMITH,ANN M' UNION ALL SELECT --8
'BHULLER, MATT' UNION ALL SELECT --9
'KIM (DAUM), GAIL' UNION ALL SELECT --10
'John.Mills';--11
with clean as
(
select original = fullname, prepped = dotted.fn, total.spaces
from #name
cross apply (values (patindex('%(%),%',fullname),fullname)) prep1(x,fn) -- check for parentheses:
cross apply (values ( -- remove parentheses if they exist, replace commas w/ dots, dots w/ spaces:
case
when prep1.x > 1 then substring(fn,1,x-1) + substring(fn,charindex(',',fn,x)+1,8000)
else replace(replace(fn, ',', '.'),'.',' ')
end)) prep(fn)
cross apply (values (replace(rtrim(ltrim(replace(prep.fn,' ',' '))),' ',' '))) clean(fn)
cross apply (values (len(clean.fn)-len(replace(clean.fn,' ','')))) total(spaces) -- count spaces
cross apply (values (replace(clean.fn, ' ','.'))) dotted(fn)
)
select original, cleaned =
case spaces
when 1 then parsename(prepped,1)+' '+parsename(prepped,2)
when 2 then parsename(prepped,2)+' '+parsename(prepped,1)+' '+parsename(prepped,3)
when 3 then parsename(prepped,2)+' '+parsename(prepped,1)+' '+parsename(prepped,3)+
' '+parsename(prepped,4)
end
from clean
Returns:
original cleaned
-------------------- ------------------
Malone,Susan M Susan M Malone
Conn,Chris G Chris G Conn
Van Pess,Wen B Wen B Pess Van
DESHPANDE, ANN W. ANN W DESHPANDE
Asif,LEE LEE Asif
CERVANTES MANDY MANDY CERVANTES
Bill, Dave Dave Bill
SMITH,ANN M ANN M SMITH
BHULLER, MATT MATT BHULLER
KIM (DAUM), GAIL GAIL KIM
John.Mills Mills John
Alternatively you can use a regex clr (mdq.regexreplace). Note my post on SSC a few years ago.

Related

I need a more reliable sort for CTE hierarchy query

Example table:
CREATE TABLE Fruit (
ID int identity(1,1) NOT NULL,
ParentID int NULL,
Name varchar(255)
);
I want to sort parent and child records from the same table in alphabetical order (more than one level deep):
Apples
--Green
----Just Sour
----Really Sour
--Red
----Big
----Small
Bananas
--etc.
I attempted this:
;WITH CTE(ID, ParentID, Name, Sort) AS
(
SELECT
ID
,ParentID
,Name
,cast('\' + Name as nvarchar(255)) AS Sort
FROM Fruit
WHERE ParentID IS NULL
UNION ALL
SELECT
a.ID
,a.ParentID
,a.Name
,cast(b.Sort + '\' + a.Name as nvarchar(255)) AS Sort
FROM Fruit a
INNER JOIN CTE b ON a.ParentID = b.ID
)
SELECT * FROM CTE Order by Sort
This produces results for the sort like:
\Apples
\Apples\Green
\Apples\Green\Just Sour
\etc.
Just when I thought things were good, it isn't reliable. For example, if an item has more than one word. Like:
\Apples
\Apples A <-- culprit
\Apples\Green
If I can expand my question while I'm at it, I'd like to show actual hyphens or something in the results:
Parent
- Child
--Grandchild
The cruddy way I quickly did this was by adding a prefix column in the table with the value of - for all records. Then I could do this:
;WITH CTE(ID, ParentID, Name, Sort, Prefix) AS
(
SELECT
ID
,ParentID
,Name
,cast('\' + Name as nvarchar(255)) AS Sort
,Prefix
FROM Fruit
WHERE ParentID IS NULL
UNION ALL
SELECT
a.ID
,a.ParentID
,a.Name
,cast(b.Sort + '\' + a.Name as nvarchar(255)) AS Sort
,cast(b.Prefix + a.Prefix as nvarchar(10)) AS Prefix
FROM Fruit a
INNER JOIN CTE b ON a.ParentID = b.ID
)
SELECT * FROM CTE Order by Sort
But that seems incorrect or not optimal.
These hierarchical queries still give me a headache, so perhaps I'm just not seeing the obvious.
I tend to use row_number() ordered by Name in this case
Example
Declare #YourTable table (id int,ParentId int,Name varchar(50))
Insert into #YourTable values
( 1, NULL,'Apples')
,( 2, 1 ,'Green')
,( 3, 2 ,'Just Sour')
,( 4, 2 ,'Really Sour')
,( 5, 1 ,'Red')
,( 6, 5 ,'Big')
,( 7, 5 ,'Small')
,( 8, NULL,'Bananas')
Declare #Top int = null --<< Sets top of Hier Try 5
Declare #Nest varchar(25) = '|-----' --<< Optional: Added for readability
;with cteP as (
Select Seq = cast(1000+Row_Number() over (Order by Name) as varchar(500))
,ID
,ParentId
,Lvl=1
,Name
From #YourTable
Where IsNull(#Top,-1) = case when #Top is null then isnull(ParentId ,-1) else ID end
Union All
Select Seq = cast(concat(p.Seq,'.',1000+Row_Number() over (Order by r.Name)) as varchar(500))
,r.ID
,r.ParentId
,p.Lvl+1
,r.Name
From #YourTable r
Join cteP p on r.ParentId = p.ID)
Select A.ID
,A.ParentId
,A.Lvl
,Name = Replicate(#Nest,A.Lvl-1) + A.Name
,Seq --<< Can be removed
From cteP A
Order By Seq
Returns
ID ParentId Lvl Name Seq
1 NULL 1 Apples 1001
2 1 2 |-----Green 1001.1001
3 2 3 |-----|-----Just Sour 1001.1001.1001
4 2 3 |-----|-----Really Sour 1001.1001.1002
5 1 2 |-----Red 1001.1002
6 5 3 |-----|-----Big 1001.1002.1001
7 5 3 |-----|-----Small 1001.1002.1002
8 NULL 1 Bananas 1002
I'm going to guess you want this result
\Apples
\Apples\Green
\Apples A
Maybe try something like this:
SELECT *
FROM CTE
ORDER BY replace(Sort, ' ', '~')
'~' is ascii 126, You can also check using excel sorting.

. It’s working fine when I pass 10-15 input but taking more than 5 minutes for 30 input. I need to make it work for 100 inputs

Here is my ask:
Go through the code and understand it.
As first solution, query should complete within 10 secs for 30 input
It should be working with good performance for 100 input as well.
My code:
/**************************************************
Populating the Array values in table variable
**************************************************/
DECLARE #PUZZLE table(
ID int IDENTITY(1,1) NOT NULL,
Value int NOT NULL)
/****Sample 1*****/
INSERT INTO #PUZZLE (value)
--SELECT 0 UNION ALL
--SELECT -22 UNION ALL
--SELECT -33 UNION ALL
--SELECT -44 UNION ALL
--SELECT 55 UNION ALL
--SELECT -100 UNION ALL
--SELECT 100 UNION ALL
--SELECT 10 UNION ALL
--SELECT -30 UNION ALL
--SELECT -60 UNION ALL
--SELECT -60 UNION ALL
SELECT -60 UNION ALL
SELECT -10 UNION ALL
SELECT 10 UNION ALL
SELECT 10 UNION ALL
SELECT -10 UNION ALL
SELECT 0 UNION ALL
SELECT -22 UNION ALL
SELECT -33 UNION ALL
SELECT -44 UNION ALL
SELECT 55 UNION ALL
SELECT -100 UNION ALL
SELECT 100 UNION ALL
SELECT 10 UNION ALL
SELECT -30 UNION ALL
SELECT -60 UNION ALL
SELECT -60 UNION ALL
SELECT -60 UNION ALL
SELECT -10 UNION ALL
SELECT 10 UNION ALL
SELECT 10
/**************************************************
Populating possible hierarchy/path
**************************************************/
DECLARE #puzHierarchy table (parentid int, childid int,value int)
INSERT #puzHierarchy (parentid,childid,value)
SELECT *-- INTO #puzHierarchy
FROM (
SELECT NULL AS ParentId,ID AS ChildId, Value
FROM #PUZZLE
WHERE ID = (SELECT MIN(ID) FROM #PUZZLE)
UNION ALL
SELECT B.Id,C.ID,C.Value
FROM #PUZZLE B
JOIN #PUZZLE C
ON C.ID > B.ID AND C.ID < (B.ID + 7)
) A
--SELECT * FROM #puzHierarchy order by parentid
/*******************************************************
Logic using recursive CTE to get the path with max value
*******************************************************/
;WITH children AS
(
SELECT ParentId
,CAST(ISNULL(CAST(ParentId AS NVARCHAR) + '->' ,'') + CAST(ChildId AS NVARCHAR) AS NVARCHAR(Max)) AS Path
,value As PathValue
FROM #puzHierarchy
WHERE ChildId = (SELECT MAX(ChildId) FROM #puzHierarchy)
UNION ALL
SELECT t.ParentId
,list= CAST(ISNULL(CAST(t.ParentId AS NVARCHAR) + '->' ,'') + d.Path AS NVARCHAR(Max))
,(t.value+d.PathValue) As PathValue
FROM #puzHierarchy t
INNER JOIN children AS d
ON t.ChildId = d.ParentId
)
SELECT [Path],PathValue
FROM children c
WHERE ParentId IS NULL
AND c.PathValue = (SELECT max(PathValue) FROM children WHERE ParentId IS NULL)
A. Your code goes through too many cycles/data unrelated to result you want.
B. After running your sample data, the results are not accurate.
Parentid Path PathValue
NULL 1->3->4->6->10->12->13->19->20 145
NULL 1->3->4->10->12->13->19->20 145
The first result is wrong.
Basically you just want starting from ParentId IS NULL and ChildId = 1, among ParentId = 1 finding which ChildId has the MAX value, this ChildId becomes ParentID to find next MAX value, and so on.
;WITH cte_base AS (SELECT Parentid
, Childid
, Value
, ROW_NUMBER() OVER(PARTITION BY Parentid ORDER BY Value DESC) AS Rownum
FROM #puzHierarchy
), cte_re AS (SELECT ParentId
, Childid
, CAST(CAST(ChildId AS NVARCHAR) AS NVARCHAR(Max)) AS Path
, Value As PathValue
, Rownum
FROM cte_base
WHERE Parentid IS NULL
UNION ALL
SELECT b.parentid, b.childid
, CAST(Path + '->' + ISNULL(CAST(b.parentid AS NVARCHAR) ,'') AS NVARCHAR(Max))
,(b.value + r.PathValue) As PathValue
, b.Rownum
FROM cte_base AS b
INNER JOIN cte_re AS r
ON b.Parentid = r.childid
where b.Rownum = 1
)
SELECT *
FROM cte_re
(I changed your sample table variable to a temporary table.)

Consolidate rows of data in SQL Server

I have multiple rows of order data which i need to consolidate in one row per part.
An example is as follows:
OrderNum PartNum Qty
-------------------------------
1 24 2
2 25 10
3 24 5
4 24 10
This then needs to be consolidated into:
OrderNum PartNum Qty
-------------------------------
1, 3, 4 24 17
2 25 10
Does anybody have any ideas how I can do this?
I have had a look around online but cannot find a solution to this use case.
Many thanks in advance,
Try this
SELECT STUFF((SELECT ',' + CAST(OrderNum AS VARCHAR(4))
FROM mytable AS s
WHERE s.PartNum = t.PartNum
FOR XML PATH('')), 1, 1, '') AS OrderNum
PartNum, SUM(Qty)
FROM mytable AS t
GROUP BY PartNum
This can be done by grouping on PartNum, sum the quantities with SUM() and concatenating strings using FOR XML PATH('') in a correlated subquery. Using FOR XML PATH('') to concatenate string is explained in this answer on SO.
DECLARE #t TABLE(OrderNum INT, PartNum INT, Qty INT);
INSERT INTO #t(OrderNum,PartNum,Qty)
VALUES(1,24,2),(2,25,10),(3,24,5),(4,24,10);
SELECT
OrderNum=STUFF((
SELECT
','+CAST(i.OrderNum AS VARCHAR)
FROM
#t AS i
WHERE
i.PartNum=o.PartNum
FOR XML
PATH(''), TYPE
).value('.[1]','VARCHAR(MAX)'),1,1,''),
o.PartNum,
Qty=SUM(o.Qty)
FROM
#t AS o
GROUP BY
o.PartNum;
Result:
OrderNum | PartNum | Qty
------------------------
1,3,4 | 24 | 17
2 | 25 | 10
SQL Server 2016 added the STRING_AGG function.
In your case, you could write
select STRING_ACC(OrderId,','),PartNum, Sum(Qty)
from MyTable
Group by PartNum
For earlier versions you'd have to use one of the techniques described by Aaron Bertrand in Grouped Concatenation in SQL Server. The fastest is to use a SQLCLR method. Next comes the FOR XML method posted by #GiorgosBetsos
DECLARE #t TABLE(OrderNum INT, PartNum INT, Qty INT)
INSERT INTO #t VALUES(1 , 24 , 2)
INSERT INTO #t VALUES(2 , 25 , 10)
INSERT INTO #t VALUES(3 , 24 , 5)
INSERT INTO #t VALUES(4 , 24 , 10)
SELECT OrderNum =
STUFF((SELECT ', ' + CONVERT(VARCHAR(50),OrderNum)
FROM #t b
WHERE b.PartNum = a.PartNum
FOR XML PATH('')), 1, 2, ''),
PartNum,
SUM(Qty) as Qty
FROM #t a
GROUP BY PartNum
Result
There are many ways to do this.
create table tablename (Name varchar(100), Rnk int)
Insert into tablename values
('Northshore', 1),
('F3', 2),
('Borderline', 3),
('Mattoon',3),
('Vinemane',5),
('Arizona',5),
('WestShore', 5),
('Schumburg', 5),
('Wilson',5)
--Method2
Select distinct
names= REPLACE(
(
Select a.Name as [data()]
From tablename A
Where A.Rnk = b.Rnk
Order by a.Name
FOR XML PATH ('') ), ' ', ',') ,Rnk
From tablename B Order by Rnk
OR
CREATE TABLE TestTable (ID INT, Col VARCHAR(4))
GO
INSERT INTO TestTable (ID, Col)
SELECT 1, 'A'
UNION ALL
SELECT 1, 'B'
UNION ALL
SELECT 1, 'C'
UNION ALL
SELECT 2, 'A'
UNION ALL
SELECT 2, 'B'
UNION ALL
SELECT 2, 'C'
UNION ALL
SELECT 2, 'D'
UNION ALL
SELECT 2, 'E'
GO
SELECT *
FROM TestTable
GO
-- Get CSV values
SELECT t.ID, STUFF(
(SELECT ',' + s.Col
FROM TestTable s
WHERE s.ID = t.ID
FOR XML PATH('')),1,1,'') AS CSV
FROM TestTable AS t
GROUP BY t.ID
GO
OR
CREATE TABLE #mable(mid INT, token nvarchar(16))
INSERT INTO #mable VALUES (0, 'foo')
INSERT INTO #mable VALUES(0, 'goo')
INSERT INTO #mable VALUES(1, 'hoo')
INSERT INTO #mable VALUES(1, 'moo')
SELECT m1.mid,
( SELECT m2.token + ','
FROM #mable m2
WHERE m2.mid = m1.mid
ORDER BY token
FOR XML PATH('') ) AS token
FROM #mable m1
GROUP BY m1.mid ;
Also, see this.
http://blog.sqlauthority.com/2009/11/25/sql-server-comma-separated-values-csv-from-table-column/

SQL Server 2012: How to find common values in a column

SQL Server 2012: How to find common values in a column
Please find below my exact requirement and help me with the Fine tuned query.
Please find below my exact requirement and help me with the Fine tuned query.
Please find below my exact requirement and help me with the Fine tuned query.
Input :
select 1, 'sankar', 'GROUPLG'
union all
select 1, 'sankar', 'GROUPLS'
union all
select 1, 'sankar', 'GROUPNG'
union all
select 1, 'sankar', 'GROUPNS'
union all
select 2, 'Srini', 'HYDRSPMLG'
union all
select 2, 'Srini', 'HYDRSPMLS'
union all
select 3, 'Ravi', 'AADSCLS'
union all
select 4, 'Arun', 'RREDFTLS'
union all
select 4, 'Arun', 'RREDFTNG'
union all
select 5, 'Raja', '1234567'
union all
select 5, 'Raja', 'ABCDESLS'
union all
select 5, 'Raja', 'ABCDESLG'
union all
select 6, 'Dhilip', 'GGGGRASCDW_RV'
Output :
-- 1 Sankar GROUP(LG,LS,NG,NS)
-- 2 Srini HYDRSPM(LG,LS)
-- 3 Ravi AADSCLS
-- 4 Arun RREDFT(LS,NG)
-- 5 Raja 1234567
-- 5 Raja ABCDESLG(LG,LS)
-- 6 dhilip GGGGRASCDW_RV
Using FOR XML PATH('') to concatenate the groups:
SQL Fiddle
SELECT
t.Userid,
t.Username,
Groupname = 'GROUP(' +
STUFF((
SELECT ',' + STUFF(GroupName, 1, 5, '')
FROM tbl
WHERE Userid = t.Userid
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)')
, 1, 1, '') + ')'
FROM tbl t
GROUP BY t.Userid, t.Username
DROP TABLE tbl
RESULT:
| Userid | Username | Groupname |
|--------|----------|--------------------|
| 1 | sankar | GROUP(LG,LS,NG,NS) |
| 2 | Srini | GROUP(LG,LS) |
| 3 | Aathi | GROUP(LS) |
Try the below code snippet -
select a.userid,a.username,
CASE WHEN PATINDEX('%,%',a.groupname) > 0 THEN
LEFT(a.groupname,PATINDEX('%,%',a.groupname)-3)+'('+REPLACE(a.groupname,LEFT(a.groupname,PATINDEX('%,%',a.groupname)-3),'')+')'
ELSE a.groupname
END as groupname
from
(select userid,username,
stuff((
select ',' + t.[Groupname]
from #users t
where t.Userid = t1.userid
order by t.[Groupname]
for xml path('')
),1,1,'') as groupname
from #users t1
group by userid,Username) a
Edit: Changed the code as per the requirement. Please re-check now.
Assuming userid + username combination is unique, please try following query. Also considering that you don't need parenthesis around group in case of a single group, I'v updated the below query.
explanation: I've used STUFF function to calculate the grouping of groups with a comma followed by every group code like LS,LG,
Now based on comparison of position of comma using CHARINDEX with length of string using LEN, we attach the logic either adding GROUP() or GROUP to the string
select
userid,
username,
CASE
WHEN CHARINDEX(',',groupname)<LEN(groupname)
THEN 'GROUP('+ SUBSTRING(groupname,1,LEN(groupname)-1) +')'
ELSE 'GROUP'+SUBSTRING(groupname,1,LEN(groupname)-1)
end as groupname
from
(
select
userid,
username,
stuff((
select
replace(groupname,'group','') + ','
from tbl
where
userid=t.userid and username=t.username
for xml path(''),type).value('.','varchar(max)'),1,0,'')
as groupname
from tbl t
group by userid, username
)t
and updated
sql fiddle link http://sqlfiddle.com/#!6/21f65/1
gives this exact output
Userid Username Groupname
1 Sankar GROUP(LG,LS,NG,NS)
2 Srini GROUP(LG,LS)
3 Aathi GROUPLS
Finally i have succeeded by the below query which i have developed. Thanks for you all. If you want You can copy the below query and execute in SSMS.
begin tran
Create table #temp (userid int, username varchar(50), groupname varchar(50))
insert into #temp(userid , username , groupname)
select 1, 'sankar', 'GROUPLG'
union all
select 1, 'sankar', 'GROUPLS'
union all
select 1, 'sankar', 'GROUPNG'
union all
select 1, 'sankar', 'GROUPNS'
union all
select 2, 'Srini', 'HYDRSPMLG'
union all
select 2, 'Srini', 'HYDRSPMLS'
union all
select 3, 'Ravi', 'AADSCLS'
union all
select 4, 'Arun', 'RREDFTLS'
union all
select 4, 'Arun', 'RREDFTNG'
union all
select 5, 'Raja', '1234567'
union all
select 5, 'Raja', 'ABCDESLS'
union all
select 5, 'Raja', 'ABCDESLG'
union all
select 6, 'Dhilip', 'GGGGRASCDW_RV'
union all
select 6, 'Dhilip', 'CDW_RV'
union all
select 6, 'Dhilip', 'GFNG'
union all
select 6, 'Dhilip', 'GFNS'
union all
select 7, 'Satya', '184518451845'
select * from #temp
select tp.userid , tp.username, groupname + CASE WHEN tp.flag = 1 THEN CASE WHEN ct.cnt > 1 then ' (' else '' end +
ISNULL(pt.grouptype1,'')+case when grouptype2 is not null
and grouptype1 is not null then ',' else '' end +
ISNULL(pt.grouptype2,'')+case when grouptype3 is not null
and (grouptype1 is not null
or grouptype2 is not null ) then ',' else '' end +
ISNULL(pt.grouptype3,'')+case when grouptype4 is not null
and (grouptype1 is not null
or grouptype2 is not null
or grouptype3 is not null) then ',' else '' end +
ISNULL(pt.grouptype4,'') + case when ct.cnt > 1 then ')' else '' end
ELSE ''
END as Permission
from (SELECT distinct userid , username, CASE WHEN RIGHT(groupname,2) IN ('LG','LS','NG','NS') THEN Substring(groupname,1,len(groupname)-2)
ELSE groupname END as groupname ,
CASE WHEN RIGHT(groupname,2) IN ('LG','LS','NG','NS') THEN 1
ELSE 0 END as flag from #temp ) tp
--WHERE Substring(groupname,1,len(groupname)-2) IN ('LG','LS','NG','NS')
join (select userid , [LG] as grouptype1 , [LS] as grouptype2 , [NG] as grouptype3 ,
[NS] as grouptype4
FROM (SELECT userid , RIGHT(groupname,2) as grouptype FROM #temp) as Sourcetable
PIVOT (MAX(grouptype)
for grouptype in ([LG],[LS],[NG],[NS])) As Pivottable) pt
ON tp.userid = pt.userid
join (select userid, count(*) as cnt from #temp group by userid ) ct
on ct.userid = tp.userid
DROP TABLE #temp
-- Expected Output
-- 1 Sankar GROUP(LG,LS,NG,NS)
-- 2 Srini HYDRSPM(LG,LS)
-- 3 Ravi AADSCLS
-- 4 Arun RREDFT(LS,NG)
-- 5 Raja 1234567
-- 5 Raja ABCDESLG(LG,LS)
-- 6 dhilip GGGGRASCDW_RV
rollback

Pairing words in sql server

Hi I have data like Below for example.
Table1:
id name
1 ab cd ef
2 john isner novak
3 roger federer murray
4 rafeal nadal grigor dmitrov
I need output as below
id pairs
1 ab cd
2 cd ef
3 john isner
4 isner novak
5 roger federer
6 federer murray
7 rafeal nadal
8 nadal grigor
9 grigor dmitrov
I have tried my best to do this and below is my code. I am new to functions and stored procedures in sql server so not familiar with it. Please help me with the code and also give me a brief about it.
CREATE TABLE YOURTABLE AS SELECT * FROM
(
SELECT PARTDESC,
CASE WHEN WORD2 IS NOT NULL THEN WORD1||' '||WORD2 END AS WORD1WORD2,
CASE WHEN WORD3 IS NOT NULL THEN WORD2||' '||WORD3 END AS WORD2WORD3,
CASE WHEN WORD3 IS NOT NULL THEN WORD3||' '||WORD4 END AS WORD3WORD4
FROM
(
SELECT PARTDESC,
REVERSE(PARSENAME(REPLACE(REVERSE(NAME), ' ', '.'), 1)) AS WORD1,
REVERSE(PARSENAME(REPLACE(REVERSE(NAME), ' ', '.'), 2)) AS WORD2,
REVERSE(PARSENAME(REPLACE(REVERSE(NAME), ' ', '.'), 3)) AS WORD3,
REVERSE(PARSENAME(REPLACE(REVERSE(NAME), ' ', '.'), 4)) AS WORD4
FROM
Table1
) A
) B
--------------------
DECLARE #colsUnpivot AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX),
#colsPivot as NVARCHAR(MAX)
select #colsUnpivot = stuff((select ','+quotename(C.name)
from sys.columns as C
where C.object_id = object_id('yourtable') and
C.name <> 'PARTDESC'
for xml path('')), 1, 1, '')
select #colsPivot = STUFF((SELECT ','
+ quotename(PARTDESC)
from yourtable t
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query
= 'select name, '+#colsPivot+'
from
(
select PARTDESC, name, value
from yourtable
unpivot
(
value for name in ('+#colsUnpivot+')
) unpiv
) src
pivot
(
max(value)
for PARTDESC in ('+#colsPivot+')
) piv'
exec(#query)
---------------
After running the above query i need to pick evry column---one column at a time and then append using union all..This is pretty much difficult task
Please help me through this...
It is possible to make this more simple and avoid dynamic sql:
DECLARE #t table(id int identity(1,1), name varchar(100))
INSERT #t VALUES
('ab cd ef'),
('john isner novak'),
('roger federer murray'),
('rafeal nadal grigor dmitrov')
;WITH CTE AS
(
SELECT row_number() over(order by id) rn,id,t.c.value('.', 'VARCHAR(2000)') splitname
FROM (
SELECT id, x = CAST('<t>' +
REPLACE(name, ' ', '</t><t>') + '</t>' AS XML)
FROM #t
) a
CROSS APPLY x.nodes('/t') t(c)
)
SELECT
row_number() over(order by cte1.id) id,
cte1.splitname + ' '+ cte2.splitname name
FROM CTE cte1
JOIN CTE cte2 ON cte1.id = cte2.id and cte1.rn + 1 = cte2.rn
Result:
id name
1 ab cd
2 cd ef
3 john isner
4 isner novak
5 roger federer
6 federer murray
7 rafeal nadal
8 nadal grigor
9 grigor dmitrov

Resources