2

假设我有以下结果集:

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-loop 可能对不同的序列成员进行过多的迭代并导致查询速度变慢。

问题:

  1. 有什么办法可以提高存储功能吗?
  2. 如果有办法,那怎么办?

我的调试查询:

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

问候。

4

1 回答 1

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,',',''))

SQLFiddle 演示

于 2013-10-03T12:59:42.750 回答