Wednesday, 29 May 2013

MSSQL - Convert list to table #1 (array of numbers in string form)

Extended version of function from this post: MSSQL - Convert list to table #2 (array of string items)
Function described here (TABLE-Value UDF) converts a string in the form "123;bbb;;;456" to tabular form.
Result will contain only non-empty items which was possible to convert to INTEGER.
In case if list has non-unique items, the function returns the serial number for each items group (RANK).

  1. -- Drop Function if exists
  2. IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'dbo.fnArray2IntTable'))
  3. DROP FUNCTION dbo.fnArray2IntTable;
  4. GO
  5.  
  6. /*=============================================
  7. Author:
  8. Yuri Abele
  9. Changes:
  10. 11.06.2013 - Yuri Abele - initial
  11. Description:
  12. Function to convert list of numeric Values to Table of integers
  13. Remark:
  14. Empty and non-numeric values will be ignored
  15.  
  16. Usage: Get all items
  17. SELECT * FROM dbo.fnArray2IntTable(N';444;bbb;333;;;333;444;555;', N';');
  18. Usage: Get all non-empty items and filter non-unique
  19. SELECT * FROM dbo.fnArray2IntTable(N';444;bbb;333;;;333;444;555;', N';') WHERE ItemRank=1;
  20. =============================================*/
  21. CREATE FUNCTION dbo.fnArray2IntTable(
  22. @Array NVARCHAR(MAX),
  23. @Delim NCHAR(1)
  24. )
  25. -- Container for Array Items
  26. RETURNS @Data TABLE(
  27. ItemIndex INT IDENTITY(1,1),
  28. ItemValue INT,
  29. ItemRank INT
  30. )
  31. AS BEGIN
  32. -- Container for XML
  33. DECLARE
  34. @XmlText NVARCHAR(MAX),
  35. @Xml XML;
  36. -- Remove empty inner items
  37. WHILE (CHARINDEX(@Delim + @Delim, @Array, 0) > 0) BEGIN
  38. SET @Array = REPLACE(@Array, @Delim + @Delim, @Delim);
  39. END;
  40. -- Remove empty left item
  41. IF(LEFT(@Array, 1) = @Delim) BEGIN
  42. SET @Array = SUBSTRING(@Array, 2, LEN(@Array)-1)
  43. END;
  44. -- Remove empty right item
  45. IF(RIGHT(@Array, 1) = @Delim) BEGIN
  46. SET @Array = SUBSTRING(@Array, 1, LEN(@Array)-1)
  47. END;
  48. -- Prepare XML-Text
  49. SET @XmlText = N'<List><Item>' +
  50. REPLACE(@Array, @Delim, N'</Item><Item>') +
  51. N'</Item></List>';
  52. -- Convert Array to XML
  53. SET @Xml = CAST(@XmlText AS XML);
  54. -- Temp Table-Variableble
  55. DECLARE @TempData TABLE(
  56. ItemIndex INT IDENTITY(1,1),
  57. ItemValue NVARCHAR(MAX)
  58. )
  59.  
  60. -- Extract Array Items to temp Table-Variable
  61. INSERT INTO @TempData
  62. SELECT
  63. Item = item.value('.', 'INT')
  64. FROM
  65. @Xml.nodes('//Item') XMLDATA(item)
  66. WHERE
  67. -- Skeep non-numeric items
  68. ISNUMERIC(item.value('.', 'NVARCHAR(MAX)')) = 1;
  69. -- Calculate Rank for each item (to find non-unique items)
  70. INSERT INTO @Data(ItemValue, ItemRank)
  71. SELECT
  72. ItemValue,
  73. ItemRank=RANK() OVER(PARTITION BY ItemValue ORDER BY ItemIndex, ItemValue)
  74. FROM
  75. @TempData
  76. ORDER BY
  77. ItemIndex;
  78.  
  79. RETURN;
  80. END;
  81.  
  82. GO
  83.  
  84. -- Get all non-empty and numeric items
  85. SELECT * FROM dbo.fnArray2IntTable(N';444;bbb;333;;;333;444;555;', N';');
  86. -- Get all non-empty and numeric items and filter non-unique
  87. SELECT * FROM dbo.fnArray2IntTable(N';444;bbb;333;;;333;444;555;', N';') WHERE ItemRank=1;


Result of execution:

No comments:

Post a Comment

Note: only a member of this blog may post a comment.