我有一个包含以下数据的表:
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
来实现这一点,但它似乎不正确,并且我无法对表中存在的值执行此操作。
答案 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;
工作原理:
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