如何将值拆分到另一列?

时间:2016-07-01 09:22:41

标签: sql sql-server

我有数据输入,想要输出图片。我该怎么写呢?

我可以在sql server中运行但是我只得到宽度列(w_pacakaging),但我不知道从列文本中写入获取值长度或高(db name:[Packing list text])

我的代码是

    select [Packing list text],[Grade],[sales doc no], 
 case when [Packing list text] like'%:%' then 
  cast(Ltrim(Rtrim(SUBSTRING([Packing list text], charindex(':', [Packing list text]) + 1, charindex('"', [Packing list text])  

  - (charindex(':', [Packing list text]) + 1)))) as [nvarchar] ) 
                       END AS [W_packaging] 
 from [TPC_CRSYS].[dbo].[TotalOrder_Export]                                            

来自sql server的结果

enter image description here

你怎么能建议我写sql从表[TotalOrder_Export]获取长度和高度的数据,因为它在每个记录中有多个x

任何人都可以建议我

1 个答案:

答案 0 :(得分:1)

使用CTE和 CHARINDEX

的简便方法
;with
T AS ( -- select the base table, adding an index for performances pourpose
    SELECT *, ROW_NUMBER() OVER (ORDER BY [sales doc no],[Packing list text]) ROW_IDX
    FROM [TPC_CRSYS].[dbo].[TotalOrder_Export]
),
W AS (-- SELECT ONLY ROWS WITH VALID DIMENSIONS AND CALC WIDTH POSITION
    SELECT *, CHARINDEX('(WXLXH): ', [Packing list text])+9 W_POS 
    FROM T
    WHERE CHARINDEX('(WXLXH): ', [Packing list text])>0
),
L AS (-- CALC LENGTH POSITION
    SELECT *, CHARINDEX('"', [Packing list text], W_POS)+2 L_POS 
    FROM W
),
H AS (-- CALC HEIGHT POSITION
    SELECT *, CHARINDEX('"', [Packing list text], L_POS)+2 H_POS 
    FROM L
),
X AS (-- CALC 
    SELECT *, CHARINDEX('"', [Packing list text], H_POS) END_POS 
    FROM H
)
SELECT T.[Packing list text], T.grade, T.[sales doc no]
, SUBSTRING(T.[Packing list text], W_POS, L_POS-2-W_POS) W
, SUBSTRING(T.[Packing list text], L_POS, H_POS-2-L_POS) L
, SUBSTRING(T.[Packing list text], H_POS, END_POS-H_POS) H
FROM T
LEFT JOIN X ON T.ROW_IDX = X.ROW_IDX

或者,您可以使用 OUTER APPLY 和拆分( FN_SPLIT )函数为每个[Packing list text]获取w / h / l行,然后 PIVOT 他们回到一行:

;with
T AS ( -- select the base table, adding an index for performances pourpose
    SELECT *, ROW_NUMBER() OVER (ORDER BY [sales doc no], [Packing list text]) ROW_IDX
    FROM [TPC_CRSYS].[dbo].[TotalOrder_Export]
),
W AS (-- SELECT ONLY ROWS WITH VALID DIMENSIONS AND CALC WIDTH POSITION
    SELECT *, CHARINDEX('(WXLXH): ', [Packing list text])+9 W_POS 
    FROM T
    WHERE CHARINDEX('(WXLXH): ', [Packing list text])>0
),
spl as (
    select W.ROW_IDX, d.*
    from w
    outer apply (
        select ID, SUBSTRING(data,2,100) VAL
        from FN_SPLIT(SUBSTRING(w.[Packing list text], w_pos-1, 100),'"') s
        where s.id<=3
    ) d
),
X AS (
    SELECT *
    FROM spl
    PIVOT (MIN(VAL) FOR ID IN ([1],[2],[3])) P
)
SELECT T.[Packing list text], T.grade, T.[sales doc no], X.[1] W, X.[2] L, X.[3] H
FROM T
LEFT JOIN X ON T.ROW_IDX = X.ROW_IDX

如果[TotalOrder_Export]表中有很多行

,则第二个版本会更快

对于分割功能,你会发现很多版本,我做了这个:

CREATE FUNCTION [dbo].[FN_SPLIT]
(
    @Line varchar(8000),
    @SplitOn varchar(10) = ','
)
RETURNS @RtnValue table
(
    Id INT NOT NULL IDENTITY(1,1) PRIMARY KEY CLUSTERED, -- VERY USEFUL TO MAKE JOINS AND TO CREATE THE UNIQUE INDEX ON SPLITTED STRINGS
    Data varchar(800) NOT NULL,
    UNIQUE (DATA, ID) -- THIS WILL MAKE REALLY FASTER THE QUERIES USING THIS FUNCTION
)
AS
BEGIN
    IF @Line IS NULL RETURN

    DECLARE @split_on_len INT = LEN(@SplitOn+'X')-1 -- TO CATCH TRAILING SPACES PROBLEM WITH LEN()
    DECLARE @line_len INT = LEN(@line+'X')-1
    DECLARE @start_at INT = 1
    DECLARE @end_at INT
    DECLARE @data_len INT

    WHILE 1=1
    BEGIN
        IF @start_at > @line_len BREAK;
        SET @end_at = CHARINDEX(@SplitOn, @Line, @start_at)
        SET @data_len = CASE @end_at WHEN 0 THEN @line_len ELSE @end_at-@start_at END
        INSERT INTO @RtnValue (data) VALUES( SUBSTRING(@Line,@start_at,@data_len));
        SET @start_at = @start_at + @data_len + @split_on_len
    END

    RETURN
END

我希望这会有所帮助