假设我有以下结果集:
SELECT
*
FROM
(
SELECT 1 as `no`, NULL as `sequence`
UNION ALL
SELECT 2, ''
UNION ALL
SELECT 3, '1'
UNION ALL
SELECT 4, '1,2,3,4,5'
UNION ALL
SELECT 5, '2,4,5'
UNION ALL
SELECT 6, '1, 5'
UNION ALL
SELECT 7, '1,3,5'
) as `sub`;
我的任务是计算下面列出的每个sequence
的序列中断/漏洞。我写了以下存储函数:
DELIMITER $$
DROP FUNCTION IF EXISTS `countSequenceBreaks`$$
CREATE FUNCTION `countSequenceBreaks`(`sequence` VARCHAR(1000))
RETURNS INT
DETERMINISTIC
BEGIN
DECLARE `delimiter` CHAR DEFAULT ',';
DECLARE `current`, `last` INT;
DECLARE `result` INT DEFAULT 0;
IF
`sequence` IS NULL
OR
NOT LENGTH(`sequence`)
OR
NOT INSTR(`sequence`, `delimiter`)
THEN RETURN `result`;
END IF;
SET `current` = SUBSTRING_INDEX(`sequence`, `delimiter`, 1);
SET `last` = SUBSTRING_INDEX(`sequence`, `delimiter`, -1);
IF `last` < `current`
THEN
SET `result` = `last`;
SET `last` = `current`;
SET `current` = `result`;
SET `result` = 0;
END IF;
WHILE `current` < `last` DO
IF NOT FIND_IN_SET(`current`, `sequence`)
THEN SET `result` = `result` + 1;
END IF;
SET `current` = `current` + 1;
END WHILE;
RETURN `result`;
END$$
DELIMITER ;
但是我担心WHILE
- 循环可能需要对不同的序列成员进行太多迭代并导致查询减速。
问题:
我的调试查询:
SELECT
`no`, `sequence`, `countSequenceBreaks`(`sequence`)
FROM
(
SELECT 1 as `no`, NULL as `sequence`
UNION ALL
SELECT 2, ''
UNION ALL
SELECT 3, '1'
UNION ALL
SELECT 4, '1,2,3,4,5'
UNION ALL
SELECT 5, '2,4,5'
UNION ALL
SELECT 6, '1, 5'
UNION ALL
SELECT 7, '1,3,5'
) as `sub`;
结果集:
no sequence `countSequenceBreaks`(`sequence`)
-----------------------------------------------
1 NULL 0
2 0
3 1 0
4 1,2,3,4,5 0
5 2,4,5 1
6 1,5 3
7 1,3,5 2
问候。
答案 0 :(得分:1)
您可以通过一个简单的查询来完成:
select sequence,
CASE WHEN NOT INSTR(IFNULL(sequence,''), ',') THEN 0
ELSE
(
SUBSTRING_INDEX(sequence,',' ,-1)
-SUBSTRING_INDEX(sequence,',' , 1)
)
-
(LENGTH(sequence)-LENGTH(REPLACE(sequence,',','')))
END countSequenceBreaks
from t
如何查找序列中断的计数?
例如1,3,5
序列。
所有我们需要知道的休息计数是计算错过的分隔符的数量。在这种情况下,完整字符串1,2,3,4,5
包含5-1=4
分隔符,但1,3,5
序列仅包含2个分隔符,因此中断计数(错过的数字 - 等于您可以看到的错过分隔符的数量)= 4-2 = 2
如何知道字符串中分隔符的数量?
在我们的情况下,当分隔符有一个符号长度时,它是(LENGTH(sequence)-LENGTH(REPLACE(sequence,',',''))