keyの最大値を取得する方法

このQ&Aのポイント
  • DB_Fileを使用して掲示板を作っています。投稿者の発言に、管理者がレスをつけるといったいわばオーソドックスなBBSです。書き込み時に書き込み数(カウント)をkeyとしてデータを格納していますが、一番大きな数字を取得する方法を教えてください。
  • %DBのキーで一番大きな数字を取得する方法について教えてください。現在、DB_Fileを使用して掲示板を作っています。投稿者の発言に、管理者がレスをつけるといったいわばオーソドックスなBBSです。
  • 掲示板を作成中で、DB_Fileを使用しています。投稿者の発言に、管理者がレスをつけるという形式のBBSです。書き込み時に書き込み数をkeyとしてデータを格納しているのですが、一番大きな数字を取得する方法を教えてください。
回答を見る
  • ベストアンサー

keyの最大値を取得する方法

こんにちは。 以前DBMについて質問したchocolatsです。 おかげさまで、なんとか使えるようになってきました! さて、現在DB_Fileを使用して掲示板を作っています。 投稿者の発言に、管理者がレスをつけるといったいわばオーソドックスなBBSです。 書き込み時に書き込み数(カウント)をkeyとしてデータを格納しているのですが、当初何も考えずに $no = scalar keys %DB; $no += 2; $DB{$no} = "$no$delim$name$delim$addr$delim・・・・"; #$delimは適当な区切り文字です としていましたが・・ これだと、当たり前の話しですが、投稿削除や、ログ消去ができないんですよね!^^; サーバーの容量が50Mですので、ログファイルにとれる容量は多くても1M以下にしておきたいのです。 かなりの件数までは保存できそうですが、いつかはデータの一部削除をしなくてはいけませんし・・ そこで、伺いたいのですが、 ■%DBのキーで一番大きな数字を取得する方法 はどういったものがあるのでしょうか。 私に考え付くのは、読み込んで、逆ソートして、一番目のデータを取得する・・といった手段ぐらいです。 これでは要領が悪い(負荷が大きい)ように感じるのですが、他にいい方法があれば、ぜひ教えていただけないでしょうか。 何か足りたい情報がありましたらお知らせください。補足します。

  • Perl
  • 回答数3
  • ありがとう数5

質問者が選んだベストアンサー

  • ベストアンサー
  • taba
  • ベストアンサー率61% (349/567)
回答No.3

>つまり、書き込み内容などの問題で部分的に記事を削除する場合は >・データは保存したままで、表示はしない(書き込みナンバーを常に連番にするなら「削除しました」と表示するなど) >という事ですよね。 ええ、そうです。 >で、データファイルから100件まとめて消す時は、消す前にトータル書き込み数を$maxなどに保存しておきそこから参照して$noを設定すればいい、という事ですよね。 ちょっと違います。消す前に$maxに保存しておくのではなく、$maxは常に最新の、最後の投稿の番号を保存してある形にしています。 私の場合は、まとめて消すというより、ファイルを大きくしないためのバックアップなので、必ず若い番号からまとめて削除します。 なので、現在データファイルにある投稿の番号が何番から何番までなのかを、$min~$maxでわかるようにしているのです。$minは当初1で、バックアップで100件削除すれば101になると。$maxは投稿があるたびに、プログラムで1ずつ増えていくので、最新の番号を指していると。こういうことです。 ただ、これはあくまでも私がそうやって作っているということであって、ひとつの考え方ですので。 ついでに少し説明しておくと、私のプログラムの場合、掲示板をデフォルトで開くと、$maxから20件をDBMから読み出して表示します(最新からの読み出し)。$maxを読むことで、表示すべきメッセージの番号が確定する($max,$max-1,$max-2,...)ので、ソートなどがいらず、プログラムもシンプルになります。 古いメッセージへさかのぼってページめくりしていくとき、どこかで最も古いメッセージへ行き当たり、それ以上表示できなくなりますよね。それを$minで管理しています。 そんな感じです。

chocolats
質問者

お礼

すみません、やっとわかりました!^^; ちょっと日本語がおかしいですが if($DB{'max'} eq ''){#最大数が設定されてなかったら $no = scalar keys %DB;#データ数を取得 }else{#入ってたら $no += $DB{'max'};#現在の書き込み数を取得 } $no++; $DB{'max'}="$no";#最大の書き込みナンバーを保存 $DB{$no} = "$no$delim$name$delim$show......"; で、削除時に削除数を$minに保存し、 読み込み時に$min>0の条件で出す、という事ですよね。 読み込み方法はtabaさんと同様の考え方になっています。 ありがとうございました!まずこれでやってみます。 しかし、念の為もうちょっと締切らないでおかせて下さい^^;

chocolats
質問者

補足

前回の確認部分は間違ってましたが・・(恥) しかし、tabaさんの考え方どうりで思ったものが出来ました!! なかなか理解できなくてごめんなさいでした^^; 詳しい解説とアドバイス本当にありがとうございました。 大感謝です!

その他の回答 (2)

  • taba
  • ベストアンサー率61% (349/567)
回答No.2

>しかし、部分的に削除した場合にはちょっと辛いですね・・。 そうですね。あくまでもまとめてバックアップを取ったときの処理で、部分的に削除したときは別のロジックで処理しています。削除したところのデータ($DB{$no}の中の$deleteとかいう変数)に削除されたことを示すフラグを立てるような形です。 >$DB{$no}のキーが、1.2.3.4...105だったとして、 >書き込み編集後1.3.8...104になるとします。 >この状態で次の書き込み時に$no=105としたいのです。 このあたりは全体の整合性を取らないといけないので、部分的に論じるとうまくいかないかもしれませんね。 ただ、maxという値を保持するというのは、つまり次の番号が何になるかを、これまでの値とは別に持っておくということです。 105まで書き込まれたとき、私のコードではmax=105になっていて、次の書き込みをするときは105に1を加えてkeyを106にします。 直前に削除があって105が無くなっていたとしても、次が106になってもいいのではないですか?(飛び番号ができるのは構わないのですよね?)何か勘違いしていたら指摘してください。 上にも書きましたが、私の使っているコードの場合、削除があってもメッセージの実体は削除せず、削除されたメッセージという扱いで「表示しない」というプログラムにしています。なので、連番は崩れないんですよね。 つまり、削除とバックアップは別になるわけです。伝わりますか?

chocolats
質問者

補足

ご丁寧な回答ありがとうございます!わかってきました・・・! つまり、書き込み内容などの問題で部分的に記事を削除する場合は ・データは保存したままで、表示はしない(書き込みナンバーを常に連番にするなら「削除しました」と表示するなど) という事ですよね。 で、データファイルから100件まとめて消す時は、消す前にトータル書き込み数を$maxなどに保存しておきそこから参照して$noを設定すればいい、という事ですよね。 この認識で間違っていたら教えていただけないでしょうか。 何度もすみません、平行してこちらも試してみますが、よろしくお願いします!

  • taba
  • ベストアンサー率61% (349/567)
回答No.1

私もDBMを使って掲示板を動かしていますが、私の場合は書き込み数の最大値を保存しています。 $max = $DB{'max'} $max++; $DB{$max} = "$max$delim$name$delim$addr$delim・・・・"; という感じでしょうか。 この場合、keyを全部取得してソートして表示するようなコードを書くときにmaxを別途処理しなければならないので気をつける必要があります。 私の場合は、常に番号を指定して呼び出す(投稿の1から10までとか)ようにしているので、同じDBに入っていても問題ないんですが。 最近はメンテナンス用に$minも設定し、数が大きくなった場合は$minを1から例えば1001に変えて、DBから1000件削除するというような対応をしています。 (表示する投稿は、$minから$maxの範囲とする) 直接の回答じゃないですけど、ひとつの考え方ということで。

chocolats
質問者

お礼

ありがとうございます! >メンテナンス用に$minも設定 なるほど、こういうやり方もあるんですね。 しかし、部分的に削除した場合にはちょっと辛いですね・・。 また、質問の仕方がいまいちでした。 $DB{$no}のキーが、1.2.3.4...105だったとして、 書き込み編集後1.3.8...104になるとします。 この状態で次の書き込み時に$no=105としたいのです。 また、例えば1000件書き込まれた時点で200件を削除するとして、 その場合にも次の書き込み時には$no=1001となればいいのですが・・ せっかくDBMを使っているのでメモリに全部読み込んでしまうのはもったいないかなと考えています。(現在はキーの総数を取得しています。) すみません、もう少しみなさんのご意見を伺わせてください。

関連するQ&A

  • WHERE句内で「値=最大値」を取得する方法

    どのようなSQLを書けばよいのかわからないので質問させてください。 以下、MasterテーブルとDataテーブルがあります。 MasterテーブルとDataテーブルのレコードを結合して取得したいと思っています。 ただし、Dataテーブルのレコードはkey1,key2,key3でグループ化した中で最新の日付の レコードと結合したいと思っています。 以下のような取得結果を想定しているのですがどのようなSQLを書けばよろしいでしょうか。 ちなみに SELECT m.key1, m.key2, m.key3, m.type, m.name, d.date, d.value FROM test.master m, test.data d; where m.key1 = d.key1 and m.key2 = d.key2 and m.key3 = d.key3 and d.date = (select Max(date) from data group by key1, key2, key3) というSQLではエラーになってしまいました。 【取得結果】 key1 key2 key3 type  name      date         value -------------------------------------------------------------------------------------------------------------  1  2   3  11   name1  2016-12-17 12:00:00    30  4  5   6  22   name2  2016-12-18 12:00:00    30  7  8   9  33   name3  2016-12-19 12:00:00    30 両者とも主キーはkey1,key2,key3となります。 【Master】 key1 key2 key3 type  name ------------------------------------------------------------  1  2   3  11   name1  4  5   6  22   name2  7  8   9  33   name3 【Data】 key1 key2 key3      date       value ---------------------------------------------------------------------------------  1  2   3   2016-12-17 10:00:00    10  1  2   3   2016-12-17 11:00:00    20  1  2   3   2016-12-17 12:00:00    30  4  5   6   2016-12-18 10:00:00    10  4  5   6   2016-12-18 11:00:00    20  4  5   6   2016-12-18 12:00:00    30  7  8   9   2016-12-19 10:00:00    10  7  8   9   2016-12-19 11:00:00    20  7  8   9   2016-12-19 12:00:00    30

    • ベストアンサー
    • MySQL
  • 静的ハッシュの配列のキーに対応する値の数の多さ順で表示させたい

    ハッシュのキーに対応する値の数の多さ順で表示させたいと考え、下記の所まで試行錯誤しておりますが、どうにも思ったようにソートできずにおります。 #!/usr/bin/perl use strict; my(%a, $i, $j ,$allarray ,@keys ,@keys2 ,%hash ,%files ,$a_mumei_ref ,$key ,$value ,@value ,$x ,$files); # ハッシュの配列を静的に作る %a = ( '0' => [ qw(0) ], '1' => [ qw(1 1) ], '3' => [ qw(3 3 3) ], '7' => [ qw(7 7 7) ], '2' => [ qw(2) ], '4' => [ qw() ], '5' => [ qw() ], '6' => [ qw() ], '8' => [ qw(8 8) ], '9' => [ qw(9) ], ); @keys = sort { $hash{$b} <=> $hash{$a} || length($b) <=> length($a) || $a cmp $b } keys %a; #ハッシュのキーを数字順で表示 foreach (@keys){ print $_ ."\n"; } # 静的に作ったハッシュの配列を取り出してみる foreach $i (sort keys %a) { for ($j = 0; $j <= scalar(@{$a{$i}})-1; $j++) { print '$a{'. $i. '}['. $j. ']='. $a{$i}[$j]. ' '; } $allarray=scalar(@{$a{$i}})-1; print "No$i:kosuu:$allarray"; print "\n"; #配列の値の個数を調べその配列を作成 my($a_mumei) = $allarray; $a_mumei_ref = \$a_mumei; $files{"$i"}=($i,$a_mumei_ref); } #each関数で%filesの中身を表示 while ( ( $key , $value ) = each %files ){ print "key:$key value:$$value\n" ; } #試行錯誤 foreach $x (sort { $files{$b} <=> $files{$a} } keys %files){ print "$x => $files->{$x}\n"; } @keys2 = sort {$hash{$a} <=> $hash{$b}} keys %files; #@keys2 = sort { $hash{$b} <=> $hash{$a} || length($b) <=> length($a) || $a cmp $b } keys %files; #@keys2 = sort { $hash{$a} cmp $hash{$b} } keys %files; print "@keys2\n"; print "\n"; __END__; 私のイメージしておりますのは、ソートした結果がハッシュのキーに対応する値の数の多さ順で下記のように表示させたいのですが、 どのようにすれば可能でございますか、ご教授願えませんでしょうか key:3 value:2・・・この場合valueは配列の個数 key:7 value:2 key:8 value:1 key:1 value:1 key:9 value:0 key:2 value:0 key:0 value:0 key:6 value:-1 key:4 value:-1 key:5 value:-1

    • ベストアンサー
    • Perl
  • クッキーに関して

    こんばんは。お世話になっております。 ここ1~2週間ほどクッキーについて学んでいるのですが、開発環境と実際のweb上での動きに違いが見られ、何がどう違うのか?が見えなくなってしまいました。下記に現状を書き留めますのでご指導頂けたら幸いに思います。 $addr = $_SERVER['REMOTE_ADDR']; setcookie("addr", $addr, time() + 60*60*24); setcookie("key_no", $key_no, time() + 60*60*24); 以上を設置すると、web上のサーバーにアップしたものに関しては、クッキーのファイルに、addr、key_no共に保存されるが、ローカルではクッキーファイル内にkey_noが見られない。 ブラウザを閉じた後、クッキー情報を取得するために、 if(isset($_COOKIE["addr"])){  $addr = $_SERVER['REMOTE_ADDR'];  $addr1 = $_COOKIE["addr"];   if($addr == $addr1){ として始めるものの、web上ではクッキーの取得に成功し、ローカル上ではクッキーを認識しない。 と、以上のような状況です。ソース的な不備も含め、ご指導いただきたく思います。お忙しい中恐縮ですが宜しくお願い申し上げます。

    • ベストアンサー
    • PHP
  • 携帯用Web画面のリファーラ値の取得方法

    環境  サーバLinux、Apache2.0.52、PHP4.3.9  携帯用Webを作成し、携帯電話からアクセスしてきた時のリンク元をgetenv("http_referer")を使用し情報を取得したいのですが取得できない状態です。尚、PCの場合は取得可能です。 log.html(対象画面) <body> このページへのアクセスが記録 <img border="0" src="http://****/log.php" width="1" height="1"> </body> log.php(記録) <?php require "config.php"; $conn = mysql_connect($sv, $user, $pass) or die("接続エラー"); mysql_select_db($dbname) or die("接続エラー"); // 値をセット $log_date = date("Y-m-d"); $log_time = date("H:i:s"); $log_ip = getenv("remote_addr"); $log_url = getenv("http_referer"); // データの追加 $sql = "INSERT INTO log (" . " log_date, " . " log_time, " . " log_ip, " . " log_url " . ") values (" . "'" . $log_date . "'," . "'" . $log_time . "'," . "'" . $log_ip . "'," . "'" . $log_url . "'" . ")"; mysql_query($sql, $conn); ?> どうかご指導のほど宜しくお願いします。

    • ベストアンサー
    • PHP
  • 欠番の取得方法

    いつも参考にさせて頂いています。 MySQL(OS:Windows)でDBを作っていますが、ある問題で詰まってしまいましたので識者の方の意見を伺えればと考えました。 問題は、インデックス(1で開始され、あとは+1ずつ増加)をキーとしたデータが登録されているテーブルがあります。 このテーブルのデータは削除・追加が行われます。削除の際は当然そのインデックスが欠番となり、追加時は欠番があればそちらを使用したいのですが、欠番を求める巧いSQLが思い浮かびません(パッと考え付くのは欠番テーブルを作る事位です…)。 如何せんDB・SQL経験が浅いためDB設計の考え方がおかしいのかもしれません。この点も含め上記問題の解決方法のヒントを教えて頂ければ幸いです。

    • ベストアンサー
    • MySQL
  • 配列からNULL以外のキーを取得したいのですが……

    配列からNULL以外のキーを取得したいです。 [0, 3]を期待しているのに、[0, 3: 3] で返ってきます。 なんででしょうか? function test(data) {  var result = [];  for (var i = 0, l = data.length; i < l; i++) {   if(data[i] !== null){    result[i] = i;   }  }  return result; } var data = ["1", null, null, "5"]; var last = test(data); console.log(last); ・console.logだから? ・もしそうなら、どうして[ 0: 1, 3: 3] ではないのでしょうか?

  • データの取得方法

    Aテーブル{ id char(3) not null, name varchar(10), a_no char(5), b_no char(5), c_no char(5), date timestamp } Bマスタ{ no char(5), name char(10) } 上記のようなDBがあるのですがAテーブルのa_no、b_no、c_noに入るのはBマスタのnoになります。 下記のようにデータを取得したい場合、どうすればうまく取得できるのでしょうか。 A.id, A.name, A.a_no, カラム名をname1としてB.name, b_no, カラム名をname2としてB.name, c_no, カラム名をname3としてB.name そんなに難しいことではないと思うのですが、考えれば考えるだけ頭の中でこんがらがってきて困っています。 よろしくお願いします。

    • ベストアンサー
    • MySQL
  • リレーションシップと外部キー制約について

    ■最終的にやりたいこと ・なるべくコード(SELECT文など)を見ずに、「DB」「テーブル定義者」「ER図」等からテーブル間の関係性を把握したい ■具体例 ・投稿一覧。「userテーブル」「postテーブル」 ・「postテーブル」の「user_id」カラムは、「userテーブル」の「id」カラムに対応 ※簡易な場合はある程度想像は付くのですが、ちょっと複雑な構成になると途端に苦労するので、何か良い方法はないかと思い、質問しました ■質問 ◆「リレーションシップを組む」際、「外部キー制約」はかけるのでしょうか? 例えば、上記「投稿一覧」DBを構築する際では、どうするのでしょうか? 1.普通、「外部キー制約」をかける 2.普通、「外部キー制約」をかけない 3.どちらでも良い ◆「外部キー制約」は何の為にかけるのでしょうか? ・「SELECT&JOIN」でデータ取得出来るのであれば、「外部キー制約」と「リレーションシップ構築」に関係性はないと思うのですが、そういう認識で合っているでしょうか? ・参照先データが削除されたら整合性がとれなくなる場合のみかけるものでしょうか? ◆「リレーションシップを確認」する目的で、「外部キー制約」をかけても良いのでしょうか? ・「データ削除の整合性」ではなく、「リレーションシップを確認」する目的で外部キー制約」をかけても良いのでしょうか? ◆「外部キー制約」以外に、「リレーションシップを確認」する方法はあるのでしょうか? ・コード(SELECT文など)を見ずに、テーブル間の「リレーションシップを確認」する方法としては、「外部キー制約」以外に何かあるのでしょうか? ・そもそも、「外部キー制約確認」=「リレーションシップ確認」という考えは正しいのでしょうか?

    • ベストアンサー
    • MySQL
  • 投稿キーが取得できない原因

    下記のような登録サイトに自サイトを登録しようとしています。 そこで質問なのですが、Firefoxだと正常に投稿キーが4桁取得できましたが、IE7、Dounut、Maxtonなどのブラウザでは1桁しか表示されず、1桁を入力しても、投稿キーが不正と表示され、登録できませんでした。Firefoxだと、4桁入力で正常に登録可能です。 他のPCでIE7で試したところ、4桁正常に表示されることが確認できたので、IE7など、ブラウザの問題ではなさそうというところまで分かりました。 そこで質問なのですが、原因としてはどんなことが考えられるか、ご教授頂けませんでしょうか。IE7でも4桁正常に表示されないのは、他のPCなどでも多く確認できているので、たまたまIEが壊れていたり、設定がおかしかったりという問題ではなさそうです。。 http://db.rankintop.com/?action=registry どうぞ、よろしくお願い致します。

  • SQLServer2000SP4のトランザクションログ削除方法

    DBをバックアップする際にトランザクションログを削除したいのですが、「データベースの保守計画」では、そのような設定はありません。そこで、「データベースの保守計画」後にトランザクションログを削除するSQLを流そうと考えているのですが、どのようなSQLかが分かりません。当サイトの過去ログを確認したところ BACKUP LOG [データベース名] WITH NO_LOG で削除可能とのことですが、全くトランザクションログは削除されません。削除方法を知っている方がおりましたら、教えてください。