An useful example in which the list of values are quite handy is the passing of multiple values within the parameter of stored procedure or function (see example). This supposes first building the list and then use the values in a dynamic build query (like in the before mentioned example) or by building a table on the fly. We can call the two operations composition, respectively decomposition of list of values.
Composition, whether on vertical or horizontal is nothing but a concatenation, in which the values alternate with one or more delimiters. Let’s reconsider the concatenation based on the values of a Person.AddressType AdventureWorks table. As the logic for concatenating for one or more attributes is the same, the below example concatenates a list based on a single attribute, namely AddressTypeID in SingleList, respectively two attributes, AddressTypeID and Name.
-- concatenation of values across a table
;WITH CTE (AddressTypeID, Name, Ranking)
AS (--preparing the data
SELECT AddressTypeID
, Name
, ROW_NUMBER () OVER(ORDER BY Name) Ranking
FROM Person.AddressType
-- WHERE ...
)
, DAT (SingleList, DoubleList, Ranking)
AS ( -- concatenating the values
SELECT Cast(AddressTypeID as varchar(max)) SingleList
, Cast('('+ Cast(AddressTypeID as varchar(10)) + ',''' + Name + ''')' as varchar(max)) DoubleList
, Ranking
FROM CTE
WHERE Ranking = 1
UNION ALL
SELECT DAT.SingleList + ',' + Cast(CTE.AddressTypeID as varchar(20)) SingleList
, Cast(DAT.DoubleList + ', ('+ Cast(CTE.AddressTypeID as varchar(10)) + ',''' + CTE.Name + ''')' as varchar(max)) DoubleList
, CTE.Ranking
FROM CTE
JOIN DAT
ON CTE.Ranking = DAT.Ranking + 1
)
-- the lists
SELECT SingleList
, DoubleList
FROM DAT
WHERE Ranking = (SELECT MAX(Ranking) FROM DAT)
The second example is based on atypical delimiters, resembling to the structure built for a batch insert or table value constructor-based statement, and as we’ll see later, ideal to be used in a dynamically-built query.
Decomposition follows the inverse path, though it’s much easier to exemplify. In fact it’s used the same technique introduced in the last example from the previous post belonging to the same cycle, Subparts of a String, in which a space was used as delimiter. Another example is the dbo.SplitList function which decomposes a string using a loop.
-- decomposition of a string to a table using CTE
CREATEFUNCTION dbo.StringToTable(
@str varchar(500)
,@Delimiter char(1))
RETURNS @Temp TABLE (
Id int NOT NULL
,Value varchar(50))
AS
BEGIN
;WITH CTE (PrevString, Position, Word)
AS (
SELECT LTrim(RTrim( CASE
WHEN CharIndex(@Delimiter, @str)>0 THEN Right(@str, Len(@str)-CharIndex(@Delimiter, @str))
ELSE ''
END)) PrevString
, 1 Position
, LTrim(RTrim(CASE
WHEN CharIndex(@Delimiter, @str)>0 THEN LEFT(@str, CharIndex(@Delimiter, @str)-1)
ELSE @str
END)) Word
UNION ALL
SELECT LTrim(RTrim(CASE
WHEN CharIndex(@Delimiter, PrevString)>0 THEN Right(PrevString, Len(PrevString)-CharIndex(@Delimiter, PrevString))
ELSE ''
END)) PrevString
, Position + 1 Position
, LTrim(RTrim(CASE
WHEN CharIndex(@Delimiter, PrevString)>0 THEN LEFT(PrevString, CharIndex(@Delimiter, PrevString)-1)
ELSE PrevString
END)) Word FROM CTE
WHERE Len(PrevString)>0
)
INSERT @Temp(Id, Value)
SELECT Position
, Word FROM CTE
OPTION (maxrecursion 100)
RETURN
END
Here are two examples based on the single list created above and another one based on alphabet:
-- decomposing SingleList
SELECT Id
, value
FROM dbo.StringToTable('6,1,2,3,4,5', ',')
-- decomposing the "alphabet"
SELECT Id
, value
FROM dbo.StringToTable('a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z', ',')
Even if the function deals only with a delimiter, it could be used to decompose lists involving multiple delimiters, as long the list is adequately built:
-- decomposing double list
SELECT Id
, value
, Left(value, CHARINDEX(',', value)-1) LeftValue
, Right(value, len(value)-CHARINDEX(',', value)) RightValue
FROM dbo.StringToTable('6,Archive;1,Billing;2,Home;3,Main Office;4,Primary;5,Shipping', ';')
The tables built thus from list of values can be further used in queries when needed to create a table on the fly. It would be interesting maybe to show that the composition and decomposition are inverse functions, however that’s out of scope, at least for current set of posts.
0 comments:
Post a Comment