String_Split по значениям таблицы - PullRequest
0 голосов
/ 08 октября 2018

У меня есть таблица со следующими данными:

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 голосов
/ 08 октября 2018

Это тот тип вещей, который вы можете легко решить, используя 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
0 голосов
/ 08 октября 2018

Как-то так должно работать ...

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
0 голосов
/ 08 октября 2018

Вы можете использовать встроенный 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 возвращает количество нулей

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...