yorek / non-scalar-uda-transitive-closure

Transitive Closure Clustering with T-SQL, SQLCLR and JSON

Home Page:https://medium.com/p/dade18953fd2

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Doesn't work in SQL Server versions prior to 2016

scrollsaw opened this issue · comments

commented

The UDA works fine, but the OPENJSON function used to parse the returning data is only available in SQL 2016+.

I've fixed this by modifying the UDA to add another class : AggregateXmlOut
It's an exact clone of the Aggregate class, the only difference is in the ToString() function:


       public override string ToString()
        {
            // this writes the output as XML instead of JSON
            // (OPENJSON is not available in SQL Server prior to 2016)

            int c = 0;
            StringBuilder sb = new StringBuilder();
            sb.Append("<ROOT>");
            foreach (var g in this._groupSet)
            {
                sb.Append("<G GId = \"" + c + "\" >");

                var ea = new int[g.Elements.Count];
                g.Elements.CopyTo(ea, 0);
                foreach (var element in ea)
                {
                    sb.Append("<M MId = \"" + element + "\" />");
                }

                sb.Append("</G>");

                c += 1;
            }

            sb.Append("</ROOT>");

            return sb.ToString();

        }

Then, create the aggregate in SSMS:


CREATE AGGREGATE [dbo].[TCC_XML]
(@id1 [INT], @id2 [INT])
RETURNS[NVARCHAR](MAX)
EXTERNAL NAME [TransitiveClosure].[TransitiveClosure.AggregateXmlOut]
GO

and finally, here is the code to test in the same manner as the original.

DECLARE @xml xml
		
select 
@xml =	dbo.[TCC_XML](id1, id2)
FROM 
TestDataBig
		

SELECT 
G.List.value ('@GId', 'int') AS GId,
M.List.value ('@MId', 'int') AS MId
FROM 
@xml.nodes('/ROOT/G')  as G(List)
CROSS APPLY G.List.nodes('M') AS M(List)

Seems about as fast as the JSON version. I tried using OPENXML to parse instead of XQUERY, but that was slower in my testing. YMMV.

Confirmed working in SQL 2012 and SQL 2017.

Cheers for writing the code in the first place, it's super useful!

Great, thanks!