问题
I have looked through a number of solutions to emulating "Group concat" functionality in SQL Server. I wanted to make a more human readable solution though and I can't work out how to do it.
I have a view:
ParentID | ChildName
Which contains the records, for example:
1 | Max
1 | Jessie
2 | Steven
2 | Lucy
2 | Jake
3 | Mark
I want to "Group Concat" these to get:
1 | Max and Jessie
2 | Steven, Lucy and Jake
3 | Mark
So If there is only 1 child, just return name, if there are more than one, concat the last 2 with an ' and ' and all others with a ', '.
I am a bit stuck on how to do this without resorting to CLR, which I don't want to do. I am happy with a function - but speed is an issue and how do I determine the child number so I can choose between ' and ', ', ' or ''?
回答1:
make a more human readable solution
Sorry, this is the best I can do with your requirement.
SQL Fiddle
MS SQL Server 2008 Schema Setup:
create table YourTable
(
ParentID int,
ChildName varchar(10)
);
insert into YourTable values
(1, 'Max'),
(1, 'Jessie'),
(2, 'Steven'),
(2, 'Lucy'),
(2, 'Jake'),
(3, 'Mark');
Query 1:
with T as
(
select ParentID,
ChildName,
row_number() over(partition by ParentID order by ChildName) as rn,
count(*) over(partition by ParentID) as cc
from YourTable
)
select T1.ParentID,
(
select case
when T2.rn = 1 and T2.cc > 1 then ' and '
else ', '
end + T2.ChildName
from T as T2
where T1.ParentID = T2.ParentID
order by T2.rn desc
for xml path(''), type
).value('substring(text()[1], 3)', 'varchar(max)') as ChildNames
from T as T1
group by T1.ParentID
Results:
| PARENTID | CHILDNAMES |
------------------------------------
| 1 | Max and Jessie |
| 2 | Steven, Lucy and Jake |
| 3 | Mark |
回答2:
select ParentID,STUFF((SELECT ' and '+ChildName
FROM Table1 where ParentID=a.ParentID
FOR XML PATH('')),1,4,'') as cnmae from Table1 a
group by ParentID
SQL FIDDLE DEMO
回答3:
Good logical question. Please check the query below (bit lengthy, but could not stop myself posting my small logic :)).
CREATE TABLE #SampleTable ([ParentID] int, [ChildName] varchar(6));
INSERT INTO #SampleTable VALUES (1, 'Max')
INSERT INTO #SampleTable VALUES (1, 'Jessie')
INSERT INTO #SampleTable VALUES (2, 'Steven')
INSERT INTO #SampleTable VALUES (2, 'Lucy')
INSERT INTO #SampleTable VALUES (2, 'Jake')
INSERT INTO #SampleTable VALUES (3, 'Mark')
select * From #SampleTable
;WITH T(xParentID, xChildName, xChildNameResult, xC1, xC2)AS
(
SELECT * FROM(
SELECT
ParentID ,
ChildName,
CAST(ChildName AS NVARCHAR(MAX)) AS ChildNameResult,
ROW_NUMBER() OVER (PARTITION BY [ParentID] ORDER BY ChildName) C1,
COUNT(*) OVER (PARTITION BY [ParentID]) C2
FROM #SampleTable)x WHERE x.C1=1
UNION ALL
SELECT ParentID, ChildName,
CAST(T.xChildNameResult+(CASE WHEN C1=1 THEN '' WHEN C1=C2 THEN ' and ' ELSE ', ' END)+ChildName AS NVARCHAR(MAX)), C1, C2
FROM
(
SELECT
ParentID ,
ChildName,
ROW_NUMBER() OVER (PARTITION BY ParentID order by ChildName) C1,
COUNT(*) OVER (PARTITION BY ParentID) C2
FROM #SampleTable
)y INNER JOIN T ON y.ParentID=T.xParentID and y.c1=T.xC1+1
)SELECT xParentID, xChildNameResult FROM T where xC1=xC2
OPTION (MAXRECURSION 0);
来源:https://stackoverflow.com/questions/13523272/sql-server-group-concat-with-different-characters