0

私は次のようなテーブルを持っています:

id
number 
year

IDではなく、カップルの年/数だけを考慮して、「穴」またはギャップを見つけたいと思います。

同じ年に2つの連続しない数値があり、その結果がその年と、それら2つの連続しない数値の間のすべての数値(極値を除く)である場合、ギャップがあります。また、下端は常に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;

したがって、使用可能なすべての年/ 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フィドルの実例


編集

DMBS固有ではないソリューションが見つからなかったので、まともなことをして、他のDBMSの例をいくつか作成したほうがいいと思いました。

SQLServerの例

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 に答える