0

partOracle DBには、以下のようないくつかのデモデータを含むテーブルがあります。

ID    NUMBER     DESCRIPTION
1     T00001     test
2     T00002     test
3     T00003     test
4     T00004     test
5     T00008     test
6     SG0001     test
7     SG0002     test
8     SG0003     test
9     SG0004     test
10    SG0006     test

この列NUMBERは、事前定義されたプレフィックスと自動増分番号のサフィックスが異なるさまざまなカテゴリ部分を定義します。現在、DBではいくつかの数値が欠落しているため、連続性が失われています。欠落した数値を一覧表示するための完璧なパフォーマンスを備えたSQLクエリまたはPL-SQL関数が必要です。

例:上記のデモデータの場合。次のデータを返す必要があります。

 Category1 start with T: T00005,T00006,T00007 
 Category1 start with SG: SG0005

誰かアイデアがありますか?

4

3 に答える 3

1

たくさんのオプションがあります。これは「島とギャップ」問題と呼ばれます。次のリソースを見てみてください(ほとんどはSQLサーバーだけでなくOracleでも機能します。微調整が必​​要な場合もあります)。

http://msdn.microsoft.com/en-us/library/aa175780(v=sql.80).aspx

また

http://www.sqlservercentral.com/articles/Advanced+Querying/anefficientsetbasedsolutionforislandsandgaps/1619/

于 2012-06-15T18:13:23.707 に答える
0

SGの場合:

WITH t AS ( 
    SELECT 
        0 as start_n, 
        p.a as end_n 
    FROM (
        SELECT MAX(TO_NUMBER(SUBSTR("NUMBER", 3))) a FROM Part p2 
        WHERE "NUMBER" LIKE 'SG%') p
)
SELECT 
    'SG' || LPAD(r.cur_num, 4, '0') AS missing_expr
FROM 
    (SELECT t.start_n + level - 1 AS cur_num FROM t CONNECT BY t.start_n + level - 1 <= t.end_n) r
WHERE 
    NOT EXISTS(
        SELECT * FROM part p WHERE p."NUMBER" = 'SG' || LPAD(r.cur_num, 4, '0')
    )
ORDER BY missing_expr ASC;

Tの場合:

WITH t AS ( 
    SELECT 
        0 as start_n, 
        p.a as end_n 
    FROM (
        SELECT MAX(TO_NUMBER(SUBSTR("NUMBER", 2))) a FROM Part p2 
        WHERE "NUMBER" LIKE 'T%') p
)
SELECT
    'T' || LPAD(r.cur_num, 5, '0') AS missing_expr
FROM 
    (SELECT t.start_n + level - 1 AS cur_num FROM t CONNECT BY t.start_n + level - 1 <= t.end_n) r
WHERE 
    NOT EXISTS(
        SELECT * FROM part p WHERE p.number = 'T' || LPAD(r.cur_num, 5, '0')
    )
ORDER BY missing_expr ASC
于 2012-06-15T17:43:37.033 に答える
0

Tの使用:

 select 'T' || substr('0000' || to_char(r.rn),length(to_char(r.rn)-1))
    from (select rownum rn from part 
        where rownum <= (select max(to_number(substr(p.number,2))) from part p 
                         where p.number like 'T%'
                        )
       ) r
     where 
      'T' || substr('0000' || to_char(r.rn),length(to_char(r.rn)-1)) 
      not in (select p.number from part p where p.number like 'T%');

SGでの使用:

select 'SG' || substr('000' || to_char(r.rn),length(to_char(r.rn)-1))
    from (select rownum rn from part 
      where rownum <= (select max(to_number(substr(p.number,3))) from part p 
                       where p.number like 'SG%'
                      )
     ) r
where 
  'SG' || substr('000' || to_char(r.rn),length(to_char(r.rn)-1)) 
  not in (select p.number from part p where p.number like 'SG%');

注意すべき点がいくつかあります。

1)テーブルPARTを使用してrownum値を取得しています。十分な行がある場合は、任意のテーブルを使用できます。このアプローチを使用する場合は、必要な範囲の値を取得するのに十分な大きさのテーブルを使用していることを確認してください。USER_OBJECTSも同様に機能する可能性があります。PARTには、操作するのに十分な値がない可能性があります。

2)列名としてのNUMBERは問題を引き起こすようです。Oracleでは予約語です。テストでは、別の列名を使用しました。

于 2012-06-15T18:11:49.217 に答える