C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[34]: c#アプリ、db設計について [1]


(過去ログ 91 を表示中)

[トピック内 36 記事 (21 - 36 表示)]  << 0 | 1 >>

■54600 / inTopicNo.21)  Re[20]: c#アプリ、db設計について
  
□投稿者/ PATIO (40回)-(2010/10/27(Wed) 11:46:59)
No54574 (ぽん さん) に返信
> 今回は最小単位を各ゲーム毎(半荘単位)をgame_idにしたいと思っています。

麻雀はあまりやら無いのでよく分かりませんけれど、
半荘単位で清算し、そのたび毎に順位を決定するのであれば、もっとも細かいデータの単位は
ある半荘であるプレーヤーが何点であがってチップが何枚と言う話になると思いますよ。
具体的には、(game_id, player_id, 点数、チップ数)を基本単位として他に必要な情報(登録時刻等)を追加するイメージかな。
この時、レコードを特定するのに必要な条件は、game_idとplayer_idです。
game_idでは任意の一つのレコードを特定できません。4レコード取れちゃいますからね。

4人でプレイしますから、一つのゲーム内の成績を取得する場合、成績テーブルをgame_idでqueryします。
結果、同じgame_idを持つデータが4レコード取れるはずです。
点数順にしたいなら点数でソートすれば良い事になります。この辺はSQLの組み方の話なりますけれど
最低限上記の情報があれば、順位等の処理はできるはずです。
点数ベースではなくて順位ベースの集計をメインにするなら各ゲーム毎の順位も記録しておくと
順位で直接集計ができますから、この辺は集計する条件を頭に入れて項目を考えます。
点数やチップ数を記録しておく事でそういう項目を対象に集計できるわけです。
逆に点数は別に必要無いのであれば、点数を項目から外すと言う方法もあります。
この辺はどうしたいか次第ですね。
順位に関しては点数を入力させてアプリケーションで勝手に付けるという手もありますよね。
どこまで入力させて何処まで自動化するのか、どういう集計をしたいのかで項目も変わりますね。

結局、何処まで毎回処理するかと言う話になりますね。
毎回処理する方法だと処理時間が毎回掛かります。
最近のPCなら毎回処理させても大して待たされる事はないでしょうから、
毎回処理させると言う選択肢もあって良いと思います。
持っている情報から毎回処理して出した方が余分なデータを持たずに済みます。
ただし、集計対象が大幅に増えたり、集計するのに作業表を作る必要があったりすると
処理時間が掛かるようになりますので、何処までを予め計算してDB上に保存しておくのか
と言う部分は状況によって判断する必要があります。

引用返信 編集キー/
■54608 / inTopicNo.22)  Re[21]: c#アプリ、db設計について
□投稿者/ ぽん (53回)-(2010/10/27(Wed) 14:15:29)
返信ありがとうございます。
半荘を1ゲーム単位と考えたいため、テーブルを少し変更してみました。

・ユーザーテーブル(id, 氏名(PK = id))
・ゲーム用テーブル(gameid, 日付, 時間, レート, チップレート, 場代単価、更新日付(PK = gameid))
・成績用テーブル(id, gameid, ポイント, チップ数, 更新日付(PK = id))

これでいけるかなと思ったのですが、この状態ですと、idが一意ではないため、
テーブルに整合性が取れなくなってしまいます。

これは成績テーブルの設計がおかしいでしょうか?
それとも他に主キーを設定すればいいのでしょうか?

よろしくお願い致します。
引用返信 編集キー/
■54613 / inTopicNo.23)  Re[22]: c#アプリ、db設計について
□投稿者/ PATIO (42回)-(2010/10/27(Wed) 14:50:10)
2010/10/27(Wed) 14:56:27 編集(投稿者)
2010/10/27(Wed) 14:53:13 編集(投稿者)

No54608 (ぽん さん) に返信
> ・成績用テーブル(id, gameid, ポイント, チップ数, 更新日付(PK = id))
>
> これでいけるかなと思ったのですが、この状態ですと、idが一意ではないため、
> テーブルに整合性が取れなくなってしまいます。

方法論的には、
gameidとidのコンポーネントキーをプライマリキーにする。
これらとは別にシーケンシャルなレコードIDを別に用意する。
あと、検索の条件につかう必要がある項目でインデックスを別に作成すると検索速度が稼げます。
その代わり、インデックスの数が増えるとデータの更新や追加に時間が掛かるようになります。
この辺はトレードオフなのでバランスを考えて設定します。

あと、プライマリーキーがユニークで無いと整合性が取れないという表現はどうかと思います。
一般的にプライマリーキーは一意性を求められるのでプライマリーキーになら無いというのが正しいかと思います。
プライマリーキーに関しては既にいろいろ説明しているHPがあるのでここでは書きません。
プライマリーキーの細かいルールに関しては使用するRDBによって若干の差がありますから、
そのRDBのリファレンスをきちんと読んで理解した上で設計しましょう。

あと、順位の集計を多用するなら順位も項目に入れておいた方が良いですよ。
その分だけ処理がすっきりする事になります。
最も一旦今の状態で作成しておいてスキーマ変更で追加とかも出来ますけれどね。

引用返信 編集キー/
■54614 / inTopicNo.24)  Re[23]: c#アプリ、db設計について
□投稿者/ ぽん (54回)-(2010/10/27(Wed) 15:26:41)
> 方法論的には、
> gameidとidのコンポーネントキーをプライマリキーにする。
> これらとは別にシーケンシャルなレコードIDを別に用意する。
すみません。コンポーネントキーがググってもヒットしなかったので質問させて下さい。

1.gameidとidのコンポーネントキーをプライマリキーにするとは成績表の主キーをgameidとidにするということでしょうか?

2.レコードidを別に用意とは成績表にレコードidというカラムを用意し、レコードid, gameid, idをプライマリキーにするということでしょうか?

私的に理解が曖昧で成績表テーブルのカラムを
レコードid, playerid, gameid, ポイント, チップ数, 更新日時
という風にしてみたのですがこれで合っていますでしょうか?

> あと、検索の条件につかう必要がある項目でインデックスを別に作成すると検索速度が稼げます。
> その代わり、インデックスの数が増えるとデータの更新や追加に時間が掛かるようになります。
> この辺はトレードオフなのでバランスを考えて設定します。

インデックスですか。。。
言葉だけしか知らず現段階では混乱しております^^;
インデックスについてはもう少し調べてみます。

引用返信 編集キー/
■54615 / inTopicNo.25)  Re[24]: c#アプリ、db設計について
□投稿者/ ぽん (55回)-(2010/10/27(Wed) 15:29:40)
>あと、順位の集計を多用するなら順位も項目に入れておいた方が良いですよ。
>その分だけ処理がすっきりする事になります。
>最も一旦今の状態で作成しておいてスキーマ変更で追加とかも出来ますけれどね。

アドバイスありがとうございます。
先ほどのテーブルにランクのカラムを追加する方向でいこうと思います^^
引用返信 編集キー/
■54618 / inTopicNo.26)  Re[24]: c#アプリ、db設計について
□投稿者/ PATIO (43回)-(2010/10/27(Wed) 18:00:40)
No54614 (ぽん さん) に返信
>>方法論的には、
>>gameidとidのコンポーネントキーをプライマリキーにする。
>>これらとは別にシーケンシャルなレコードIDを別に用意する。
> すみません。コンポーネントキーがググってもヒットしなかったので質問させて下さい。
>
> 1.gameidとidのコンポーネントキーをプライマリキーにするとは成績表の主キーをgameidとidにするということでしょうか?
>
> 2.レコードidを別に用意とは成績表にレコードidというカラムを用意し、レコードid, gameid, idをプライマリキーにするということでしょうか?

コンポーネントキーって一般用語じゃなかったのか。
gameidとidでひとつのキーとして設定する方法です。
定義上は複数のカラムをPKとして指定する方法になります。
確か並び順も考慮に入れたほうが良かったはずです。
レコードidを別に設けると言うのは、個人的にはコンポーネントキーをPKにするのが
気持ち悪いからで、この場合はレコードidは単なるシーケンシャルな数字でかまいません。


> 私的に理解が曖昧で成績表テーブルのカラムを
> レコードid, playerid, gameid, ポイント, チップ数, 更新日時
> という風にしてみたのですがこれで合っていますでしょうか?

それでもOKだと思います。
レコードidを単なるレコード番号だと考えるならオートインクリメントをカラムに設定しておく
手も有ります。これだと追加した時点で勝手にインクリメントされます。


>>あと、検索の条件につかう必要がある項目でインデックスを別に作成すると検索速度が稼げます。
>>その代わり、インデックスの数が増えるとデータの更新や追加に時間が掛かるようになります。
>>この辺はトレードオフなのでバランスを考えて設定します。
>
> インデックスですか。。。
> 言葉だけしか知らず現段階では混乱しております^^;
> インデックスについてはもう少し調べてみます。

RDBを使う上でインデックスはとても大事な物なのでいろいろ調べて理解しておく事を
お勧めします。大量データに対して検索を行う時にインデックスが設定されているかどうかで
検索速度が天と地ほど違います。

引用返信 編集キー/
■54620 / inTopicNo.27)  Re[25]: c#アプリ、db設計について
□投稿者/ ちゃっぴ (45回)-(2010/10/27(Wed) 18:25:27)
ちゃっぴ さんの Web サイト
> コンポーネントキーって一般用語じゃなかったのか。

Composite primary key とか。
引用返信 編集キー/
■54623 / inTopicNo.28)  Re[26]: c#アプリ、db設計について
□投稿者/ PATIO (46回)-(2010/10/27(Wed) 18:36:53)
No54620 (ちゃっぴ さん) に返信
>>コンポーネントキーって一般用語じゃなかったのか。
>
> Composite primary key とか。

コンポジットキーだったかも。
あー、間違って記憶してるなぁ。
失礼しました。

引用返信 編集キー/
■54628 / inTopicNo.29)  Re[27]: c#アプリ、db設計について
□投稿者/ ぽん (56回)-(2010/10/27(Wed) 20:49:16)
コンポジットキーありました!

gameid, idをキーにしてレコードidを追加した場合gameidが重複すると怒られてしまいました。

ちなみにレコードid, gameid, idをコンポジットキーとすると上手くいきます。
順番とかが違うのでしょうか。。。

>それでもOKだと思います。
>レコードidを単なるレコード番号だと考えるならオートインクリメントをカラムに設定しておく
>手も有ります。これだと追加した時点で勝手にインクリメントされます

レコードidをIDENTITIYありにしてみました。しかし番号が飛んでしまうようです。
これは削除したレコード等があるとその分の番号も記憶しているからでしょうか?

引用返信 編集キー/
■54629 / inTopicNo.30)  Re[28]: c#アプリ、db設計について
□投稿者/ ぽん (57回)-(2010/10/27(Wed) 20:55:48)
> >それでもOKだと思います。
> >レコードidを単なるレコード番号だと考えるならオートインクリメントをカラムに設定しておく
> >手も有ります。これだと追加した時点で勝手にインクリメントされます

IDENTITYを設定しなおすクエリを飛ばせばいいのですね。
ということは削除されたレコードがあった場合このようなクエリを作成すればいいんでしょうか?

今まではプログラム側でレコード数を元に変更していたので、どちらが汎用的なのか分からず。。。
連レスすみません。
引用返信 編集キー/
■54651 / inTopicNo.31)  Re[29]: c#アプリ、db設計について
□投稿者/ PATIO (49回)-(2010/10/28(Thu) 14:51:01)
2010/10/28(Thu) 14:54:39 編集(投稿者)

まず、レコードidは、gameidとplayeridのコンポジットキーをPKにしたくない
と言う意図で入れるのでレコードidを入れるのならレコードidを素直にPKにした方が良いです。
レコードidで検索するのという話はあると思いますけれど。
逆にgameidとplayeridのコンポジットキーをPKにするのであれば、レコードidは必要無いと
思います。レコードidを使って何かしたいということであれば、良いと思いますけれど。

RDBのテーブルの設定でカラムの属性としてオートインクリメントを設定していると
レコードが追加されるたびにインクリメントされてシーケンシャルな番号が振られます。
ただし、レコードの削除を行なうとその部分は番号が欠番になります。

オートインクリメントを設定されているカラムは参照はしても更新はしません。
追加時もデータを設定する必要は有りません。
オートインクリメント以外の項目の値だけを指定して追加すれば、勝手に数値が設定されます。
オートインクリメントを使う場合、そのカラムのデータ型によりますが、
データ型の上限まで行ってしまうとidが枯渇してしまいます。
どんなに増えてもここまでと言うレコード数を把握した上で使う必要が有りますよ。

オートインクリメントは使う側が楽をする為の物なので
オートインクリメントを使わずに最新のレコードidを把握して
レコード追加時に自分で設定できるのであれば、無理に使う必要が有りません。
但し、これを自前で行う為には現在の最後尾のidを把握しておく必要があるので、この管理をどうするのかと言う話は考えておく必要があります。


とか、この辺の話はRDBのリファレンスにあるはずなのでその部分に関しては勉強してください。
RDBを使いこなす為には必要な知識になりますから。

引用返信 編集キー/
■54657 / inTopicNo.32)  Re[30]: c#アプリ、db設計について
□投稿者/ ぽん (58回)-(2010/10/28(Thu) 18:03:48)
返信ありがとうございます。

> まず、レコードidは、gameidとplayeridのコンポジットキーをPKにしたくない
> と言う意図で入れるのでレコードidを入れるのならレコードidを素直にPKにした方が良いです。
> レコードidで検索するのという話はあると思いますけれど。
> 逆にgameidとplayeridのコンポジットキーをPKにするのであれば、レコードidは必要無いと
> 思います。レコードidを使って何かしたいということであれば、良いと思いますけれど。

むしろgameidとplayeridのコンポジットキーをPKにしたのですが、そうすると、
データ入力時にplayeidが重複した場合、怒られてしまって。。。

う〜ん。。。順番が悪いのでしょうか?

それともレコードidをおとなしくキーにしてしまうほうがいいでしょうか?



引用返信 編集キー/
■54666 / inTopicNo.33)  Re[31]: c#アプリ、db設計について
□投稿者/ PATIO (50回)-(2010/10/28(Thu) 21:20:35)
2010/10/28(Thu) 21:30:32 編集(投稿者)
2010/10/28(Thu) 21:27:48 編集(投稿者)

No54657 (ぽん さん) に返信
> むしろgameidとplayeridのコンポジットキーをPKにしたのですが、そうすると、
> データ入力時にplayeidが重複した場合、怒られてしまって。。。

時間があるのでしたらここはじっくり行きましょう。
中途半端に進めてしまっても後々疑問が残ったままになってしまいます。
テーブルを作成する部分はどのように行なっていますか?
MySQLを使う事が多くてSQLServerは使わないのでその辺が良く分からないですが。

もしかしてgameidとplayeridにユニーク制約をつけていませんか?
コンポジットキーとしてPKにする場合、
それぞれの項目を単独で見た時はユニークでは無いのでユニーク制約をつけると
当然、重複エラーになると思いますけれど。
というか、単独ではユニークでないからコンポジットキーにしているわけですよね。
この辺は、ユニーク制約をどうして付けるのかを考えてみて下さい。
ユニークで無いと困る事がわかっているからその項目に対してユニーク制約をかけて
データの整合性を保とうとしているわけです。
ユニークになりえない項目に対してはユニーク制約をつけてはいけません。

この辺は割りとベーシックな話だと思うので入門書等で確認されると良いと思います。

追伸:
気になったのですが、gameidとplayeridをセットで見た時に成績テーブル上に同じ項目のセットを持つデータがあったりしますか?
例えばですが、同一のgameidで同じplayeridを持つレコードが二つ以上出来るような状態だとPKとしてはだめと言う事になります。
私は、同じgameidを持つ成績レコードは4つ、つまりその時に参加していたplayeridしか無いと思っていたのですけれど。
つまり、(gameid, playerid)= (1,1)、(1,2)、(1,3)、(1,4)の四つと言う意味です。(つまりセットで見たときは重複しない)
引用返信 編集キー/
■54670 / inTopicNo.34)  Re[32]: c#アプリ、db設計について
□投稿者/ ぽん (59回)-(2010/10/28(Thu) 21:50:12)
No54666 (PATIO さん) に返信
> 2010/10/28(Thu) 21:27:48 編集(投稿者)
>
> ■No54657 (ぽん さん) に返信
>>むしろgameidとplayeridのコンポジットキーをPKにしたのですが、そうすると、
>>データ入力時にplayeidが重複した場合、怒られてしまって。。。
>
> 時間があるのでしたらここはじっくり行きましょう。
> 中途半端に進めてしまっても後々疑問が残ったままになってしまいます。
> テーブルを作成する部分はどのように行なっていますか?
> MySQLを使う事が多くてSQLServerは使わないのでその辺が良く分からないですが。
>
> もしかしてgameidとplayeridにユニーク制約をつけていませんか?
> コンポジットキーとしてPKにする場合、
> それぞれの項目を単独で見た時はユニークでは無いのでユニーク制約をつけると
> 当然、重複エラーになると思いますけれど。
> というか、単独ではユニークでないからコンポジットキーにしているわけですよね。
> この辺は、ユニーク制約をどうして付けるのかを考えてみて下さい。
> ユニークで無いと困る事がわかっているからその項目に対してユニーク制約をかけて
> データの整合性を保とうとしているわけです。
> ユニークになりえない項目に対してはユニーク制約をつけてはいけません。
>
> この辺は割りとベーシックな話だと思うので入門書等で確認されると良いと思います。

してきありがとうございます。了解しました!
調べてみますね^^♪

> 追伸:
> 気になったのですが、gameidとplayeridをセットで見た時に成績テーブル上に同じ項目のセットを持つデータがあったりしますか?
> 例えばですが、同一のgameidで同じplayeridを持つレコードが二つ以上出来るような状態だとPKとしてはだめと言う事になります。
> 私は、同じgameidを持つ成績レコードは4つ、つまりその時に参加していたplayeridしか無いと思っていたのですけれど。

すみません。。。もう一度やり直したら上手くいきました。。。orz
本当にすみませんでした。

ちなみに場所などを入れようとおもっていたのですが、店によって単価(1h/円)が違うので店テーブルにその情報を、
入れることにしました。その際、1ゲーム単位ではなく、ゲーム終了(例えば5ゲーム終わって全ての清算をする)時に時間と場代単価を掛けて計算したいと思っています。
なので、時間と日付は別テーブルにいれようかなと思っています。(1日の区切りですかね?)上手く説明出来なくてすみません。

取りあえずまた設計してみます^^



引用返信 編集キー/
■54671 / inTopicNo.35)  Re[33]: c#アプリ、db設計について
□投稿者/ PATIO (52回)-(2010/10/28(Thu) 21:55:03)
No54670 (ぽん さん) に返信

> ちなみに場所などを入れようとおもっていたのですが、店によって単価(1h/円)が違うので店テーブルにその情報を、
> 入れることにしました。その際、1ゲーム単位ではなく、ゲーム終了(例えば5ゲーム終わって全ての清算をする)時に時間と場代単価を掛けて計算したいと思っています。
> なので、時間と日付は別テーブルにいれようかなと思っています。(1日の区切りですかね?)上手く説明出来なくてすみません。

複数のゲームを束ねて一つのグループとして扱えるような概念があるとうまく説明できそうです。
店が変われば、違うグループとみるとかですね。

引用返信 編集キー/
■54696 / inTopicNo.36)  Re[34]: c#アプリ、db設計について
□投稿者/ ぽん (60回)-(2010/10/29(Fri) 13:07:04)
おはようございます。

>複数のゲームを束ねて一つのグループとして扱えるような概念があるとうまく説明できそうです。
>店が変われば、違うグループとみるとかですね。

それが出来たらいいですよね♪
ただ混乱してきました。。。

テーブルを
・プレイヤー登録マスタ
・ショップ登録マスタ
・1半荘ゲーム用
・グループごとゲーム用
・成績用
にわけて設計してみました。

プレイヤー登録マスタ(プレイヤーid, プレイヤー名)PK = プレイヤーid
ショップ登録マスタ(店id, 店名, 場代単価)PK = 店id
1半荘ゲーム用(ゲームid, 日付, レート, チップレート)PK = ゲームid
グループごとゲーム用(グループid, プレイヤーid, 店id, time, 場代)PK = グループid, プレイヤーid
成績用(グループid, プレイヤーid, ゲームid, 順位, ポイント, チップ枚数)PK = グループid, プレイヤーid, ゲームid
という風にしてみました。

自分としてはゲーム最小単位(半荘)で取得したいのは順位、ポイント、チップ金額です。
グループごとに取得したいのは時間、店、場代になります。

なのでプレイヤーid、ゲームidを指定すればそのゲームの順位、ポイント、チップ金額が、
グループid、プレイヤーid、ゲームidを指定すればそのグループ、氏名ごとのポイント合計、チップ金額合計、時間、場代等を取得出来ればいいと思っています。

上記テーブルで問題点ありますでしょうか?

にしても全然スマートじゃないですね。。。^^;

あとインデックスも考えなくては。。。orz
引用返信 編集キー/

<前の20件
トピック内ページ移動 / << 0 | 1 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -