开发者

How to split cell content and extract information into a new column in an SQL select statement?

开发者 https://www.devze.com 2022-12-21 03:53 出处:网络
I have a table where one of the columns are storing key/value pairs separated by semicolons, like this:

I have a table where one of the columns are storing key/value pairs separated by semicolons, like this:

KEY1:VALUE1;KEY2:VALUE2;KEY3:VALUE3

I would like to construct a view开发者_Go百科 where I have additional columns where the value will be extracted from the field above. My question is how to extract VALUE1, VALUE2 and VALUE3 in a SELECT query.

There will not be more than three key-value pairs in this field.


I've already answered an incredibly similar question today, so look at the answer:

SQL comma delimted column => to rows then sum totals?

but try this:

I prefer the number table approach to split a string in TSQL

For this method to work, you need to do this one time table setup:

SELECT TOP 10000 IDENTITY(int,1,1) AS Number
    INTO Numbers
    FROM sys.objects s1
    CROSS JOIN sys.objects s2
ALTER TABLE Numbers ADD CONSTRAINT PK_Numbers PRIMARY KEY CLUSTERED (Number)

Once the Numbers table is set up, create this split function:

CREATE FUNCTION [dbo].[FN_ListToTable]
(
     @SplitOn  char(1)      --REQUIRED, the character to split the @List string on
    ,@List     varchar(8000)--REQUIRED, the list to split apart
)
RETURNS TABLE
AS
RETURN 
(

    ----------------
    --SINGLE QUERY-- --this will not return empty rows
    ----------------
    SELECT
        ListValue
        FROM (SELECT
                  LTRIM(RTRIM(SUBSTRING(List2, number+1, CHARINDEX(@SplitOn, List2, number+1)-number - 1))) AS ListValue
                  FROM (
                           SELECT @SplitOn + @List + @SplitOn AS List2
                       ) AS dt
                      INNER JOIN Numbers n ON n.Number < LEN(dt.List2)
                  WHERE SUBSTRING(List2, number, 1) = @SplitOn
             ) dt2
        WHERE ListValue IS NOT NULL AND ListValue!=''

);
GO 

You can now easily split a CSV string into a table and join on it:

select * from dbo.FN_ListToTable(',','1,2,3,,,4,5,6777,,,')

OUTPUT:

ListValue
-----------------------
1
2
3
4
5
6777

(6 row(s) affected)

Your can now use a CROSS APPLY to split every row in your table like:

DECLARE @YourTable table (RowID int, RowValue varchar(200))
INSERT INTO @YourTable VALUES (1,'KEY11:VALUE11;KEY12:VALUE12;KEY13:VALUE13')
INSERT INTO @YourTable VALUES (2,'KEY21:VALUE21;KEY22:VALUE22;KEY23:VALUE23')
INSERT INTO @YourTable VALUES (3,'KEY31:VALUE31;KEY32:VALUE32;KEY33:VALUE33')


SELECT
    o.RowID,RIGHT(st.ListValue,LEN(st.ListValue)-CHARINDEX(':',st.ListValue)) AS RowValue
    FROM @YourTable  o
        CROSS APPLY  dbo.FN_ListToTable(';',o.RowValue) AS st

OUTPUT:

RowID       
----------- -------
1           VALUE11
1           VALUE12
1           VALUE13
2           VALUE21
2           VALUE22
2           VALUE23
3           VALUE31
3           VALUE32
3           VALUE33

(9 row(s) affected)


Writing a scalar function, which receives the string containing the key/value pairs, and the index of the value to get (or the key of the value to get) as its arguments, and returns the appropriate value, would make your problem easily solvable.

You could also write this scalar function in .Net, which would perform a lot better than writing it in TSQL, as you wouldn't have to access any tables or database objects from that function.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号