0

我有一张像这样的桌子:

id
number 
year

我想找到“漏洞”或差距,不考虑 id 而只考虑几年/数字。

当同一年有两个不连续的数字时存在差距,结果是年份和这两个不连续数字之间的所有数字(不包括极端数字)。另请注意,下端始终为 1,因此如果缺少 1,则为间隙。

例如,拥有:

id  n   year
1   1   2012   
2   2   2012
3   5   2012
4   2   2010

我想要的结果是:

3/2012
4/2012
1/2010
4

2 回答 2

3

在序列中查找缺失条目的技巧是生成序列中所有可用组合的笛卡尔积,然后用于NOT EXISTS消除那些存在的组合。这很难以非 DBMS 特定的方式完成,因为它们都有不同的方式来优化动态创建序列。对于 Oracle,我使用:

SELECT  RowNum AS r
FROM    Dual
CONNECT BY Level <= MaxRequiredValue;

因此,要生成所有可用 year/n 对的列表,我将使用:

SELECT  d.Year, n.r
FROM    (   SELECT  year, MAX(n) AS MaxN 
            FROM    T 
            GROUP BY Year
        ) d
        INNER JOIN
        (   SELECT  RowNum AS r
            FROM    Dual
            CONNECT BY Level <= (SELECT MAX(n) FROM T)
        ) n
            ON r < MaxN;

我得到每年的最大值 n 并将其加入从 1 到最高 n 的整数列表中,其中该整数列出的最大值小于该年份的最大值。

最后用于NOT EXISTS消除已经存在的值:

SELECT  d.Year, n.r
FROM    (   SELECT  year, MAX(n) AS MaxN 
            FROM    T 
            GROUP BY Year
        ) d
        INNER JOIN
        (   SELECT  RowNum AS r
            FROM    Dual
            CONNECT BY Level < (SELECT MAX(n) FROM T)
        ) n
            ON r = MaxN
WHERE   NOT EXISTS
        (   SELECT  1
            FROM    T
            WHERE   d.Year = t.Year
            AND     n.r = t.n
        );

SQL Fiddle上的工作示例


编辑

由于我找不到非 DMBS 特定的解决方案,我想我最好做点正经的事,并为其他 DBMS 创建一些示例。

SQL Server 示例

PostgreSQL 示例

我的 SQL 示例

于 2012-06-26T10:03:47.863 回答
0

另一种选择是使用这样的临时表:

create table #tempTable ([year] int, n int)

insert 
into    #tempTable
select  t.year, 1
from    tableName t 
group by    t.year

while exists(
    select  *
    from    tableName t1
    where   t1.n > (select MAX(t2.n) from #tempTable t2 where t2.year = t1.year)
)
begin

    insert 
    into    #tempTable
    select  t1.year, 
        (select MAX(t2.n)+1 from #tempTable t2 where t2.year = t1.year)
    from    tableName t1
    where   t1.n > (select MAX(t2.n) from #tempTable t2 where t2.year = t1.year)

end

delete  t2
from    #tempTable t2
inner join  tableName t1
on  t1.year = t2.year
and t1.n = t2.n

select  [year], n
from    #tempTable

drop table  #tempTable
于 2012-06-26T10:16:58.533 回答