SQL逻辑拆分值

时间:2018-10-08 20:23:08

标签: sql sql-server tsql split

我在下面的列中有值,并且我想将值分成多个列值

前4个字符代表位置代码 后3个字符代表费用代码 最后6个字符代表帐户代码

COLUMN A
---------------
AA12.F07.123456
XX34 SA8 676868
YY13_SS3_798798
HJ88.657769
.898798

预期输出:

ColA    ColB    ColC
---------------------
AA12    F07     123456
XX34    SA8     676868
YY13    SS3     798798
HJ88    NULL    657769
NULL    NULL    898798

最后一行没有3位数字的成本代码 最后一行没有4位数的位置代码

您能告诉我如何实现吗?

3 个答案:

答案 0 :(得分:1)

只需使用substring()并明智地使用模式匹配:

select (case when a like '[^_. ][^_. ][^_. ][^_. ][_. ]%' then left(a, 4) 
        end) as col1,
       (case when a like  '[^_. ][^_. ][^_. ][^_. ][_. ][^_. ][^_. ][^_. ][^_. ][_. ]%' then substring(a, 6, 3) 
        end) as col2,
       (case when a like '[^_. ][^_. ][^_. ][^_. ][^_. ][^_. ]' then right(a, 6) end) as col3

答案 1 :(得分:1)

根据您的示例,以下内容应会为您带来所需的结果...

IF OBJECT_ID('tempdb..#TestData', 'U') IS NULL 
BEGIN   -- DROP TABLE #TestData;
    CREATE TABLE #TestData (
        ColumnA VARCHAR(17) NOT NULL 
        );

    INSERT #TestData(ColumnA) VALUES
        ('AA12.F07.123456'),
        ('XX34 SA8 676868'),
        ('YY13_SS3_798798'),
        ('HJ88.657769'),
        ('.898798');
END;

--SELECT * FROM #TestData td;

--==========================================

SELECT 
    td  .ColumnA,
    ca.ColA,
    cb.ColB,
    cc.Colc
FROM
    #TestData td
    CROSS APPLY ( VALUES (CASE WHEN td.ColumnA LIKE '[0-Z][0-Z][0-Z][0-Z][^0-Z]%' OR td.ColumnA LIKE '[0-Z][0-Z][0-Z][0-Z]' THEN SUBSTRING(td.ColumnA, 1, 4) END) ) ca (ColA)
    CROSS APPLY ( VALUES (CASE WHEN td.ColumnA LIKE '%[^0-Z][0-Z][0-Z][0-Z][^0-Z]%' THEN SUBSTRING(td.ColumnA, 6, 3) END) ) cb (ColB)
    CROSS APPLY ( VALUES (CASE WHEN td.ColumnA LIKE '%[0-Z][0-Z][0-Z][0-Z][0-Z][0-Z]' THEN RIGHT(td.ColumnA, 6) END) ) cc (Colc);

结果:

ColumnA           ColA ColB Colc
----------------- ---- ---- ------
AA12.F07.123456   AA12 F07  123456
XX34 SA8 676868   XX34 SA8  676868
YY13_SS3_798798   YY13 SS3  798798
HJ88.657769       HJ88 NULL 657769
.898798           NULL NULL 898798

答案 2 :(得分:1)

Jason Long发布的是我要做的方式。根据他的回答,我将其简化为一个CROSS APPLY,并且没有CASE语句:

SELECT t.ColumnA,
       colA = SUBSTRING(t.ColumnA, col.a, 4), 
       colB = SUBSTRING(t.ColumnA, col.b, 3),
       colC = SUBSTRING(t.ColumnA, col.c, 6)
FROM   #TestData AS t
CROSS APPLY (VALUES(
  NULLIF(PATINDEX('[A-Z][A-Z][0-9][0-9][^A-Z0-9]%', t.ColumnA),0),
  NULLIF(PATINDEX('%[^A-Z0-9][A-Z][A-Z0-9][A-Z0-9][^A-Z0-9]%', t.ColumnA),0)+1,
  NULLIF(PATINDEX('%[0-9][0-9][0-9][0-9][0-9][0-9]', t.ColumnA),0))) AS col(a,b,c);