在表的值上String_Split

时间:2018-10-08 19:09:35

标签: sql sql-server tsql

我有一个包含以下数据的表:

SequenceID Values
____________________________________
1   111111111111111111111100000111110000
2   111111111111000000000000011110000001
3   111111111110000000000000000000000011
4   111111111100000111111000000000000111
5   111111111000000011111111100000001111
6   111111110000000000111111110000011111
7   111111100000000111111111000000111111
8   111111000000001111111000000000111111
9   111110000000011111100000000000111111
10  111100000000000000000000000000111111

检索只有零或一的序列的最佳方法是什么。例如,如果我只想检索零,我会得到类似的东西:

SequenceID  Zeros
_________________
1           5
1           4
2           13
2           6
3           23
ETC

OR

SequenceID  Zeros
_________________
1           '00000'
1           '0000'
2           '0000000000000'
2           '000000'
3           '00000000000000000000000'
ETC

我试图使用STRING_SPLIT来实现这一点,但它似乎不正确,并且我无法对表中存在的值执行此操作。

3 个答案:

答案 0 :(得分:4)

这是您可以使用PatternSplitCM轻松解决的问题。

-- Sample Data
DECLARE @table TABLE (SequenceID INT, [Values] CHAR(36));
INSERT @table VALUES
(1 ,  111111111111111111111100000111110000),
(2 ,  111111111111000000000000011110000001),
(3 ,  111111111110000000000000000000000011),
(4 ,  111111111100000111111000000000000111),
(5 ,  111111111000000011111111100000001111),
(6 ,  111111110000000000111111110000011111),
(7 ,  111111100000000111111111000000111111),
(8 ,  111111000000001111111000000000111111),
(9 ,  111110000000011111100000000000111111),
(10,  111100000000000000000000000000111111);

-- solution
SELECT t.SequenceID, zeros = LEN(s.Item) 
FROM   @table AS t
CROSS APPLY dbo.PatternSplitCM(t.[Values],'0') AS s
WHERE  s.[Matched] = 1;

结果:

SequenceID  zeros
----------- -----------
1           5
1           4
2           13
2           6
3           23
4           5
4           12
5           7
5           7
6           10
6           5
7           8
7           6
8           8
8           9
9           8
9           11
10          26

答案 1 :(得分:1)

您可以使用内置的STRING_SPLIT(SQL Server 2017):

SELECT SequenceId, LEN(value) AS zeros, value
FROM tab t
CROSS APPLY(SELECT replace(replace(replace(t.val,'1','<>'),'><',''),'<>','1')) s(r)
CROSS APPLY STRING_SPLIT(s.r, '1')
WHERE value != ''
ORDER BY SequenceId;

db<>fiddle demo

工作原理:

1)首先CROSS APPLY删除多个'111'->'1'

2)使用CROSS APPLY作为分隔符的第二个1拆分字符串

3)WHERE过滤出空字符串

4)LEN返回零个数字

答案 2 :(得分:1)

类似的事情应该起作用...

IF OBJECT_ID('tempdb..#TestData', 'U') IS NULL 
BEGIN   -- DROP TABLE #TestData;
    CREATE TABLE #TestData (
        SequenseID INT NOT NULL PRIMARY KEY CLUSTERED,
        SeqValue CHAR(36) NOT null
        );

    INSERT #TestData (SequenseID, SeqValue) VALUES
        (1, '111111111111111111111100000111110000'),
        (2, '111111111111000000000000011110000001'),
        (3, '111111111110000000000000000000000011'),
        (4, '111111111100000111111000000000000111'),
        (5, '111111111000000011111111100000001111'),
        (6, '111111110000000000111111110000011111'),
        (7, '111111100000000111111111000000111111'),
        (8, '111111000000001111111000000000111111'),
        (9, '111110000000011111100000000000111111'),
        (10, '111100000000000000000000000000111111');
END;

--SELECT * FROM #TestData td;

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

SELECT 
    xxx.SequenseID,
    ZeroCount = COUNT(1),
    Zeros = REPLICATE('0', COUNT(1))
FROM
    (
    SELECT 
        td.SequenseID,
        grp_start = t.rn - ROW_NUMBER() OVER (PARTITION BY td.SequenseID ORDER BY t.rn)
    FROM
        #TestData td
        CROSS APPLY (   -- this creates a 36 row tally table on the fly.
            SELECT 
                rn = ROW_NUMBER() OVER (ORDER BY x.n)
            FROM
                ( VALUES 
                    (1),(1),(1),(1),(1),(1),
                    (1),(1),(1),(1),(1),(1),
                    (1),(1),(1),(1),(1),(1),
                    (1),(1),(1),(1),(1),(1),
                    (1),(1),(1),(1),(1),(1),
                    (1),(1),(1),(1),(1),(1) 
                ) x (n)
            ) t
    WHERE 
        SUBSTRING(td.SeqValue, t.rn, 1) = '0'
    ) xxx
GROUP BY
    xxx.SequenseID,
    xxx.grp_start
ORDER BY 
    xxx.SequenseID,
    xxx.grp_start;

结果:

SequenseID  ZeroCount   Zeros
----------- ----------- -----------------------------------
1           5           00000
1           4           0000
2           13          0000000000000
2           6           000000
3           23          00000000000000000000000
4           5           00000
4           12          000000000000
5           7           0000000
5           7           0000000
6           10          0000000000
6           5           00000
7           8           00000000
7           6           000000
8           8           00000000
8           9           000000000
9           8           00000000
9           11          00000000000
10          26          00000000000000000000000000