检测整数序列中的间隙

时间:2014-06-30 14:51:55

标签: sql postgresql

意图:检测数字序列是否包含间隙。无需识别缺失的元素,只需标记(true / false)序列(如果它包含间隙)。

CREATE TABLE foo(x INTEGER);
INSERT INTO foo(x) VALUES (1), (2), (4);

下面是我(显然正常运行的)查询以检测间隙:

WITH cte AS
(SELECT DISTINCT x FROM foo)
SELECT 
(  (SELECT COUNT(*)   FROM cte a 
                CROSS JOIN cte b
                         WHERE b.x=a.x-1)
  =(SELECT COUNT(*)-1 FROM cte))
OR (NOT EXISTS (SELECT 1 FROM cte))

表格为空的边缘情况需要OR。查询的逻辑基于以下观察:在连续序列中,链接数等于元素数减1。

更具惯用性或高性能(我应该担心特别长序列中的CROSS JOIN?)

4 个答案:

答案 0 :(得分:2)

试试这个:

SELECT 
CASE WHEN ((MAX(x)-MIN(x)+1 = COUNT(DISTINCT X)) OR 
           (COUNT(DISTINCT X) = 0)  )
           THEN 'TRUE'
           ELSE 'FALSE'
END   
FROM foo 

SQLFiddle demo

答案 1 :(得分:2)

以下内容应检测是否存在缺口:

select (case when max(x) - min(x) + 1 = count(distinct x)
             then 'No Gaps'
             else 'Some Gaps'
        end)
from foo;

如果没有间隙或重复,则x的不同值的数量是最大值减去min加1。

答案 2 :(得分:1)

另一种方法......

如果从最大值中减去最小值,并加1,则应该等于计数。

如果count =(max-min)+1,那么“没有差距!”

如果你能在SQL中表达它,它应该非常有效。

答案 3 :(得分:1)

SELECT 'Has ' || count(*) - 1 || ' gaps.' AS gaps
FROM   foo f1
LEFT   JOIN foo f2 ON f2.id = f1.id + 1
WHERE  f2.id IS NULL;

诀窍是计算行,缺少下一行 - 如果没有间隙,则只发生 last 行。

如果没有行,则会获得'Has -1 gaps.' 如果没有差距,则会获得'Has 0 gaps.' 否则,'Has n gaps.' .. n是确切的间隙数,无论多大 对于重复项,可以增加计数,但0-1不受欺骗的影响。