This creates input
myid
|
COMMENT
|
1
|
concat
|
1
|
concat2
|
1
|
concat3
|
1
|
test
|
2
|
concaxt
|
2
|
concaxt2
|
2
|
concaxt3
|
2
|
testx
|
And generates the output of:
myid
|
COMMENT
|
1
|
concat, concat2, concat3, test
|
2
|
concaxt, concaxt2, concaxt3, testx
|
/*
This example provides two methods for concatonating records. The first method is a pure sql method that works with common table expressions.
The second uses a "trick" that can be done with the current versions of microsoft sql to concat records, it is much faster but may not be usable
in future versions.
*/
IF Object_id('tempdb..#tmp') IS NOT NULL
BEGIN
DROP TABLE #tmp
END
CREATE TABLE #tmp
(
myid INT,
comment VARCHAR(255)
)
INSERT INTO #tmp
(myid,
comment)
SELECT 1,
'test'
UNION
SELECT 1,
'concat'
UNION
SELECT 1,
'concat2'
UNION
SELECT 1,
'concat3'
UNION
SELECT 2,
'testx'
UNION
SELECT 2,
'concaxt'
UNION
SELECT 2,
'concaxt2'
UNION
SELECT 2,
'concaxt3'
/*
Quick example on how to concatonate records with a CTE
*/
;
WITH rownumsfororder
AS (
/* Sort the records in the order you want to concatonate them for there id in this case we use row num!*/
SELECT myid,
comment,
Row_number()
OVER (
partition BY myid
ORDER BY comment ) row_num
FROM #tmp),
concatenations
AS (
--Recursively concactonate the records in the order defined above, this makes lots of records and makes this super slow! I bet
-- there is a trick somewhere that can do this faster!
SELECT myid,
CONVERT(NVARCHAR(max), comment) COMMENT,
row_num
FROM rownumsfororder
WHERE row_num = 1
UNION ALL
SELECT c.myid,
( c.comment + ', ' + l.comment ) COMMENT,
l.row_num
FROM concatenations c -- this is a recursion!
INNER JOIN rownumsfororder l
ON l.myid = c.myid
AND l.row_num = c.row_num + 1),
-- Now we want to sort so that we get the "deepest" of the recursively created records
-- This "deepest" record will have the highest row number. Again, something might be doable above to just simply
-- choose only good records for this, if you know how to make this faster, send this email back with better examples.
row_numedconcatenations
AS (SELECT myid,
comment,
Row_number()
OVER (
partition BY myid
ORDER BY row_num DESC ) row_num
FROM concatenations),
concatedlist
AS (
/*
This gets the concatonated comment
*/
SELECT *
FROM row_numedconcatenations
WHERE row_num = 1)
-- The final set you can then join to your main set of data or pipe into another temp table for a later join.
-- Enjoy!
SELECT *
FROM concatedlist
--- This is another, much faster, method of doing concatonations. The only thing this does not have is flexibility
-- in the type of concats you can do, IE you can do no transformations on the data like you can with the CTE
-- recursion. IF you just want to concat the records, but not prune the records in any way, then this is a good way to go.
-- This may not work in future versions.
SELECT x.myid,
LEFT(x.comments, Len(x.comments) - 1) AS comments
FROM (SELECT t1.myid,
(SELECT comment + ','
FROM #tmp AS t2
WHERE t2.myid = t1.myid
ORDER BY comment
FOR xml path('')) AS comments
FROM #tmp AS t1
GROUP BY t1.myid) AS x
This example provides two methods for concatonating records. The first method is a pure sql method that works with common table expressions.
The second uses a "trick" that can be done with the current versions of microsoft sql to concat records, it is much faster but may not be usable
in future versions.
*/
IF Object_id('tempdb..#tmp') IS NOT NULL
BEGIN
DROP TABLE #tmp
END
CREATE TABLE #tmp
(
myid INT,
comment VARCHAR(255)
)
INSERT INTO #tmp
(myid,
comment)
SELECT 1,
'test'
UNION
SELECT 1,
'concat'
UNION
SELECT 1,
'concat2'
UNION
SELECT 1,
'concat3'
UNION
SELECT 2,
'testx'
UNION
SELECT 2,
'concaxt'
UNION
SELECT 2,
'concaxt2'
UNION
SELECT 2,
'concaxt3'
/*
Quick example on how to concatonate records with a CTE
*/
;
WITH rownumsfororder
AS (
/* Sort the records in the order you want to concatonate them for there id in this case we use row num!*/
SELECT myid,
comment,
Row_number()
OVER (
partition BY myid
ORDER BY comment ) row_num
FROM #tmp),
concatenations
AS (
--Recursively concactonate the records in the order defined above, this makes lots of records and makes this super slow! I bet
-- there is a trick somewhere that can do this faster!
SELECT myid,
CONVERT(NVARCHAR(max), comment) COMMENT,
row_num
FROM rownumsfororder
WHERE row_num = 1
UNION ALL
SELECT c.myid,
( c.comment + ', ' + l.comment ) COMMENT,
l.row_num
FROM concatenations c -- this is a recursion!
INNER JOIN rownumsfororder l
ON l.myid = c.myid
AND l.row_num = c.row_num + 1),
-- Now we want to sort so that we get the "deepest" of the recursively created records
-- This "deepest" record will have the highest row number. Again, something might be doable above to just simply
-- choose only good records for this, if you know how to make this faster, send this email back with better examples.
row_numedconcatenations
AS (SELECT myid,
comment,
Row_number()
OVER (
partition BY myid
ORDER BY row_num DESC ) row_num
FROM concatenations),
concatedlist
AS (
/*
This gets the concatonated comment
*/
SELECT *
FROM row_numedconcatenations
WHERE row_num = 1)
-- The final set you can then join to your main set of data or pipe into another temp table for a later join.
-- Enjoy!
SELECT *
FROM concatedlist
--- This is another, much faster, method of doing concatonations. The only thing this does not have is flexibility
-- in the type of concats you can do, IE you can do no transformations on the data like you can with the CTE
-- recursion. IF you just want to concat the records, but not prune the records in any way, then this is a good way to go.
-- This may not work in future versions.
SELECT x.myid,
LEFT(x.comments, Len(x.comments) - 1) AS comments
FROM (SELECT t1.myid,
(SELECT comment + ','
FROM #tmp AS t2
WHERE t2.myid = t1.myid
ORDER BY comment
FOR xml path('')) AS comments
FROM #tmp AS t1
GROUP BY t1.myid) AS x
No comments:
Post a Comment