Reputation: 6798
How to simulate string_agg function ?
I need get this
[value]
1
2
3
into this
1,2,3
I tried following
CREATE TYPE stringArray AS TABLE ([value] nvarchar(255))
GO
CREATE FUNCTION dbo.ufn_join
(
@table stringArray readonly,
@separator nvarchar(5) = ','
)
RETURNS nvarchar(max)
AS
BEGIN
RETURN stuff((select @separator + value from @table for xml path('')), 1, 1, '')
END
GO
SELECT dbo.ufn_join(
(
SELECT cast(1 as nvarchar(255)) as value
UNION
SELECT cast(2 as nvarchar(255)) as value
UNION
SELECT cast(3 as nvarchar(255)) as value
)
, DEFAULT
)
but I am getting an error
-- Error: Operand type clash: nvarchar is incompatible with stringArray
Only condition is that i do not want to use any kind of variables. CLR function is also totally fine, but there i have the same issue, how to insert return of select as a parameter to the function.
Upvotes: 1
Views: 12577
Reputation: 3591
Normally I use this link when I want to concat rows. There are several options how to do it, so here you can find inspiration on which approach you like the most. Be aware of XML PATH since it uses all of your CPU Processes and can max out your CPU to 100%.
Example from the link:
CREATE FUNCTION dbo.udf_select_concat ( @c INT )
RETURNS VARCHAR(MAX) AS BEGIN
DECLARE @p VARCHAR(MAX) ;
SET @p = '' ;
SELECT @p = @p + ProductName + ','
FROM Northwind..Products
WHERE CategoryId = @c ;
RETURN @p
END
SELECT CategoryId, dbo.udf_select_concat( CategoryId )
FROM Northwind..Products
GROUP BY CategoryId ;
Upvotes: 2
Reputation: 7928
TVP issue aside, your function will be profoundly faster and more efficient by turning it into an inline table valued function (commonly referred as an inline scalar function (iSF)). This article explains what I'm saying in detail: How to Make Scalar UDFs Run Faster (SQL Spackle)
CREATE FUNCTION dbo.ufn_join (@separator nvarchar(5))
RETURNS TABLE WITH SCHEMABINDING AS RETURN
SELECT concatinatedTxt =
stuff((select @separator + someTxt from dbo.someTable for xml path('')), 1, 1, '');
Upvotes: 2
Reputation: 358
It's because you declared a type, set that type to a parameter and the tried to insert a table into this parameter (a different type).
Try this:
CREATE TYPE stringArray AS TABLE ([value] nvarchar(255))
GO
CREATE FUNCTION dbo.ufn_join
(
@table stringArray readonly,
@separator nvarchar(5) = ','
)
RETURNS nvarchar(max)
AS
BEGIN
RETURN stuff((select @separator + value from @table for xml path('')), 1, 1, '')
END
GO
DECLARE @table stringArray
INSERT INTO @Table
SELECT cast(1 as nvarchar(255)) as value
UNION
SELECT cast(2 as nvarchar(255)) as value
UNION
SELECT cast(3 as nvarchar(255)) as value
SELECT dbo.ufn_join(
@Table
, DEFAULT
)
Upvotes: 1