-2

0から6,00,000までの値をとるフィールドがあります

このフィールドのデータベースの値は、たとえば5,6,7,8,45,91,92,93,94です。

このフィールドの無料の値と使用済みの値の提案を取得する必要があります

1.USED
最小値=0最大値=94(データベースから)

私はforループを使用します(i = minvalue; i <= maxvalue; i ++)この場合、ループは94回実行され、データベースエントリ(5,6,7,45..94)と一致するかどうかをチェックするたびに実行されます。


使用値のような出力範囲を出力
します:5〜8
45 91〜94

値が少ないため、高速に動作します。データベースに490000のようなエントリが1つでもあった場合、ループは非常に長い間実行されていたでしょう。

2.FREE
最小値=0最大値=600000(フィールド定義から)

ここでも同じforループの概念があるので、ループは5lac回実行されます。そして、出力が来ることはありません。時間がかかりすぎます。


Free値のような出力が必要です:
0〜4
9〜44
46〜90
95-600000

forループの実行を減らす方法や他のロジックを使用する方法はありますか?

4

3 に答える 3

3

そうしないでください。

可能であれば、このデータベース列をAUTO_INCREMENT(またはSQLエンジンの最も近い代替)として設定して、新しい値が自動的に割り当てられるようにします。それが不可能な場合は、代わりSELECT MAX(col) + 1 FROM tableに次に利用可能な値を決定できます(ただし、これは人種が発生しやすいことに注意してください)。

どちらの場合も、ギャップを残すことを心配しないでください。ほとんどのアプリケーションでは、それは問題ではありません。アプリケーションにドメイン要件が存在し、IDの数が限られている場合(なぜですか?)、とにかくすべてのIDが割り当てられると、最終的に問題が発生する可能性があるため、これを計画する必要があります。

効率的に割り当てる必要のある使用可能な値が少数あるという非常に珍しい状況にある場合は、それらの値を明示的に追跡する必要があります。使用可能な値ごとに1行のテーブルと、それが何に割り当てられているかを示すフィールドを用意し、のようなものを使用してそのテーブルを検索しますSELECT id FROM id_table WHERE inuse = 0 LIMIT 1

于 2013-01-11T05:59:49.507 に答える
0

データベーステーブルにN行がある場合、0からNまでの値の少なくとも1つは未使用である必要があるため、ループする必要があるのは最大でN +1回だけです。

Perlでこれを行う効率的な方法は、使用された値をハッシュキーとして格納し、変数がハッシュ内のどのキーとも一致しなくなるまでループ内で変数をインクリメントすることです。

my @values = (5,6,7,8,45,91,92,93,94);

my %hash;
undef @hash{@values};

my $x = 0;
$x++ while exists $hash{$x};

# now $x is the lowest unused value
于 2013-01-11T05:48:26.187 に答える
0

特定の範囲のすべての値をループする必要はありません。値を調べて、連続する値(たとえば、現在の値が前の値より1大きい)またはギャップをそれぞれ探します。これははるかに高速になります。

使用範囲を印刷するには

my @values = (5, 6, 7, 8, 45, 91, 92, 93, 94);
my $start = shift @values;
my $i = $start;
for my $v (@values) {
    if ($v > $i + 1) {
        if ($i == $start) {
            print "$start\n";
        } else {
            print "$start to $i\n";
        }

        $start = $v;
    }

    $i = $v;
}

if ($i == $start) {
    print "$start\n";
} else {
    print "$start to $i\n";
}

と自由値の範囲を見つけるために

my @values = (5, 6, 7, 8, 45, 91, 92, 93, 94);
my $i = 0;
my $max = 600000;
for my $v (@values) {
    if ($v > $i + 1) {
        print "$i to ", $v - 1, "\n";
    } elsif ($v == $i + 1) {
        print "$i\n";
    }

    $i = $v + 1;
}

if ($i < $max) {
    print "$i to $max\n";
}
于 2013-01-11T09:48:04.037 に答える