2013-10-03 79 views
2

想,我有以下結果集:如何高效地計算MySQL中的序列中斷/空洞?

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 

問候。

回答

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分隔符所以休息的計數(未接數字 - 什麼是等於錯過了COUNT分隔符,你可以看到)= 4-2 = 2

如何知道分隔符的數量在字符串中?

在當定界符具有一個符號長度是(LENGTH(sequence)-LENGTH(REPLACE(sequence,',',''))

SQLFiddle demo

+0

感謝我們的情況......你是天才要比! – BlitZ

相關問題