DB設計を語るスレ 3

このエントリーをはてなブックマークに追加
1NAME IS NULL
引き続き語れ!!

前スレ
DB設計を語るスレ 2
http://pc11.2ch.net/test/read.cgi/db/1223458453/

過去スレ
DB設計を語るスレ
http://pc11.2ch.net/test/read.cgi/db/1166540159/
2NAME IS NULL:2010/04/07(水) 09:27:33 ID:???
またサロゲート厨か
3NAME IS NULL:2010/04/14(水) 19:34:41 ID:???
T字形ERマスターの俺様が華麗に2ゲット!
4NAME IS NULL:2010/04/17(土) 02:43:18 ID:???
有給と勤怠の管理システム作ってるけど、
有給の設計むずいな。前年度の繰越とか
5NAME IS NULL:2010/04/17(土) 18:26:32 ID:???
社員 今年残 前年残
A     20   15
B     5    9

で消化するとき今年残から先に減らせばいいだけ
繰越は単に今年残→前年残、今年残→規定リストからセットで済む
6NAME IS NULL:2010/04/18(日) 17:34:12 ID:???
なにそのくそせっけい
7NAME IS NULL:2010/04/18(日) 22:26:32 ID:???
どうしろと
8NAME IS NULL:2010/04/21(水) 00:38:45 ID:GuWbcNTa
簡単なのでいいから勤怠管理の設計載ってるサイト教えて下さい
9NAME IS NULL:2010/04/21(水) 14:58:34 ID:???
俺だったら、年次ごとに与えられた日数と消化した日数は別々に保存する。
計算結果だけ保存するのは、俺の感が駄目だと言ってる。
10NAME IS NULL:2010/04/22(木) 03:22:06 ID:???
有給テーブル
取得日
日数

勤怠テーブル
日付
出勤時間
退社時間
勤怠区分

勤怠区分テーブル
勤怠区分

有休残計算はストアドとかで
11NAME IS NULL:2010/04/30(金) 13:54:02 ID:???
T字型マスターの俺様、なんとか言ってやってください!
12NAME IS NULL:2010/05/04(火) 21:11:32 ID:???
自分達に無い物を作ろうとするから、どう設計すれば良いのか見えないんじゃね?
13NAME IS NULL:2010/05/06(木) 17:59:31 ID:???
有休テーブル
+社員ID
+年次(っぽいもの)
+付与日数

有休実績テーブル
+社員ID
+年次(っぽいもの)
+消化日数

有休実績テーブル(案2)
+社員ID
+取得開始年月日
+取得終了年月日

今現在の有休残はストアドとかで
14NAME IS NULL:2010/05/06(木) 23:53:16 ID:???
>>13
有給実績テーブルの消化日数って、有給テーブルにくっつけたらダメなの?なんでわけてんの?
15NAME IS NULL:2010/05/07(金) 00:51:45 ID:???
13じゃないのに勝手に答えるけど、
それだと付与・消化の属性を追加して使い分けるとか
あるいはrowそのものを書き換える必要が出てくるじゃない

テーブルで分けといた方が分かりやすいと思うな
休んだ日数を細切れでブっこんでおいて、全体の消化日数はID&年次でselectしてsum取ればいいし
16NAME IS NULL:2010/05/07(金) 10:15:44 ID:???
>>14
有給の付与が年度の開始時にしか起こらないって脳内ルールを作ってないか?
17NAME IS NULL:2010/05/07(金) 12:14:53 ID:???
つまりそれは回りまわって>>12に帰結するわけだな(涙
18NAME IS NULL:2010/05/07(金) 20:15:10 ID:???
有効期限があるポイントを管理しなきゃならんのだわ。
やっぱり1ポイント1レコードかしら?

それとも「何月何日に100ポイント取得」「何月何日に30ポイント消費」みたいな、
ログ記録かしら。

教えてちょんまげ。
19NAME IS NULL:2010/05/07(金) 21:11:50 ID:???
直したのかよ
有給ないやつにも分かるように直したのかよ
20NAME IS NULL:2010/05/08(土) 06:31:21 ID:???
>>16
有給は半年前倒しで全社員一斉に与えても
いいんだよ。でなければ、入社日から計算。
入社半年で、0.5年度。一年半で1.5年度。
年度は入社何年目かって事でしょ。西暦
じゃないよ。この年度単位でないと、
繰越計算しにくいと思う。だから、年度に
与えた日数と消化した日数持たせていい。

>>15
なんかいまいちその利点がイメージできない。消化日数を持たせた時点で、集計
してrowをその都度更新していくのは
当たり前だし。それに、本当にsumなんか
で繰越の計算できんの?
2113:2010/05/10(月) 11:33:11 ID:???
実際に消化した実績日数だけで良いシステムなら、同一テーブルでもいいけど、
大抵は、事前に申請が必要だし、その申請こみで今現在の残日数を求める必要が
あったりする。つまり、大抵は(案2)みたいなテーブルが必要になるだろうってこと。
22NAME IS NULL:2010/05/17(月) 23:44:56 ID:???
そういえば最近は時間単位で年休取得できる会社もあるよな。
23NAME IS NULL:2010/05/18(火) 00:21:58 ID:???
時間単位はややこしい。日単位なら
その日の勤怠区分で処理できるのに。
例えば、10時出勤でも遅刻でないとか、
しかし、そのその日の勤務時間は一時間
マイナスで、有給で一時間補充とか、考えるだけで鬱になる
24NAME IS NULL:2010/06/15(火) 00:30:24 ID:???
簡単相互リンク集みたいなのを作ってまして
初めてDBをまともに使うのですが、こんな設計で問題ないでしょうか?

仕組みとしては、
・ひとつのUserIDに複数のサイトを登録可能
・申請が承認されると表示される
・相手にはUserIDは秘匿。

UserTable
---------------------
UserID | Mail         |  Password   | 自分のSiteIDs     | 承認待ち              | 申請中
---------------------
u2145  | [email protected]  |   1234     | s3265,s2664,       | s3526(相手) to s3265(自分),   | s3265(自分) to s4377(相手)


SiteTable
---------------------
SiteID | UserID | URL         | Title    | ビットフラグ        | ジャンル     | 紹介文       | リンクしているSiteIDs
---------------------
s3265 | u2145 | http://google.com/ | Google  | 未認証,リンク切れ,etc   | 検索/リンク集 | 検索サイトです。 | s6325,s2355,s2362,s2355,


(未認証は、本人のサイトか未確認の意味。仮登録後、数時間未認証の場合テーブルから削除します。別のテーブル作ったほうがいいのかな)

リンク集生成時にURLとタイトルを取得する為に複数のSiteIDを問い合わせるので、心配なのですが
普段はHTMLファイルを生成して追加/削除するときにHTMLファイルを更新する感じにすれば問題ないでしょうか?
アドバイスよろしくお願いします。
25NAME IS NULL:2010/06/15(火) 01:58:11 ID:???
>>24
ユーザー毎にテーブル作った方がいい
26NAME IS NULL:2010/06/15(火) 06:01:44 ID:???
to に笑った
27NAME IS NULL:2010/06/15(火) 06:15:29 ID:???
「s3265,s2664」とかなってるのはカラムの中にカンマ区切りにするって意味?
そんなんDB使う意味ないぞ。テキストデータで持ってた方がマシなレベル。
それに静的データ(マスタ)と動的ステータスは完全に分けた方がいいがごっちゃになってる
それと未認証とリンク切れとか意味が全く違うものを一緒にしちゃいかん。

>>25
ユーザが増えたらcreate table発行か?ありえん。
2824:2010/06/15(火) 06:42:19 ID:???
レスありがとうこざいます。


>>27

カンマ区切りでした。。SQL側でひとつのカラムに複数の値を管理できるのでしょうか?
よければヒントの検索ワード教えてもらえませんかTT
(カラムにレヒードを追加できるのでしょうか!?)

ビットフラグでカラム減らそうとしてました。
素直にtrue/falseでそれぞれカラムあったほうがいいんでしょうか?

静的と動的はこの場合、頻繁に書き換わるSiteIDが動的?ですかね
UserTableの申請中などの情報は新しいテーブルに作ってみます。

29NAME IS NULL:2010/06/15(火) 07:01:33 ID:???
>カラムに複数の値を管理
配列を入れられるDBもあるけど検索に使いづらくなるのでまずやらない。
そういう場合、RDBは複数レコードで管理する。もちろん行数は多くなるが管理や検索速度のバランスだからしゃーない。

んで、テーブルだが、ちょっと要件いまいちわかってなくて考察適当だがこんな感じだと思うぞ。
UserMasterTable (UserID(PK)|Mail|Password)
SiteMasterTable (SiteID(PK)|サイトのUserID|URL|ジャンル|紹介文|リンク切れフラグ|未認証フラグ)
SiteLinkStatusTable (リンク元SiteID(PK)|リンク先SiteID(PK)|ステータス(未承認/承認済/削除)|更新日時)

SiteLinkStatusTableは申請時1レコード、承認されて相互リンクになると2レコードになる。
未認証→認証を行うのは管理者でいいの?
30NAME IS NULL:2010/06/15(火) 07:19:50 ID:???
>>29
すごく具体的ありがとうこざいます> <

なるほど、こんなテーブルになるのですか!
素人考えで一つのテーブルに纏めすぎてたんですね ; ;

認証は管理者ですね。リンク切れは定期的に確認する感じです。

ちょっと私には複雑すぎてSQL質疑応答スレで聞くことになると思いますが
とりあえず寝てから作成してみます。
31NAME IS NULL:2010/06/15(火) 16:32:38 ID:???
未認証とリンク切れは一緒でいいんじゃまいか
認証されてなければリンク切れとは判定しないだろうし
0 = 正常 / 1 = 未認証 / 2 = リンク切れ
とでもすれば
32NAME IS NULL:2010/06/15(火) 17:42:05 ID:???
まあ、なんにせよ要件次第ではあるが

>>29
>仮登録後、数時間未認証の場合テーブルから削除します
なので、サイトマスターに最低限、申請(仮登録)日時いるだろうな
そうなると本登録日とか、ほかにも項目ほしくなるだろうけど

>>31
・未認証で承認しようとしたらリンクが切れてました
・承認してたんだけど、ある日リンクが切れました
の二つを区別して記録したいなら分けておかないとだめじゃね
もしくは別途サイト登録履歴みたいなテーブルもたせるか
3324:2010/06/15(火) 18:22:47 ID:???
皆様ありがとうこざいます

作ろうとしてるのは、ユーザーのサイトにphpファイル(名前と設置場所固定)を設置させて被リンク効果を出す感じなのですが
phpファイル自体は、
$SiteID = 235455;
$fp = fopen("ttp://www.mydomain.com/site/$SiteID.html", "rb") or die ("Cannot open");
fpassthru($fp);
こんな感じでURLを取得して表示してるだけです。

後出しなのですが
未認証は、phpファイルが設置されていない状態で
リンク切れは、トップページからそのphpファイルにリンクされてない状態です。
相互リンク中に未認証/リンク切れになった場合は、一定時間後にSiteLinkStatusTableからサイト事消す感じになります。

そして後から気づいたのですが、リンク申請にメッセージを添えられる予定だったので
新たにMessageBoxTableを作ってみました。(メッセージボックスはユーザーが自由に消去できる予定)

UserMasterTable (UserID(PK)|Mail|Password|メールを受け取るか)
SiteMasterTable (SiteID(PK)|サイトのUserID|URL|タイトル|紹介文|ジャンル|ページランク|バックリンク|ステータス(未認証/リンク切れ/正常)|ステータスが変わった日時)
SiteLinkStatusTable (リンク元SiteID(PK)|リンク先SiteID(PK)|更新日時)
MessageBoxTable ( ユニークID(PK) | 差出人SiteID | 宛先SiteID | タイトル | 本文 | フラグ(リンク申請/リンク不成立/削除報告) | 日時 )

UserIDとSiteIDは登録時間のUNIXタイムスタンプを使おうかと思ってます。
34NAME IS NULL:2010/06/15(火) 19:08:29 ID:???
UNIXタイムスタンプはダメだ
DATETIME型でカラム作った方がいいぞ
35NAME IS NULL:2010/06/15(火) 20:37:55 ID:NSd5kCf1
在庫調査のDBを作ろうとしてるのですが、
差分データのようにしないとデータ多すぎて一ヶ月もしないうちに大変な事になってしまいそうです。
エリア、店名、商品名、価格、個数、調査時間
最低限保持しないといけないのが上記項目で
同じ店でも同じ商品名でも陳列が別なら別登録になります。(ヤフオクで同じ商品が同じ価格でずらっと並んでるような)
調査1回につき、20〜30エリア、1〜100店、商品1〜100点、個数1〜100程度になるので単純にDBに登録すると1回で最大時30万行になってしまいます。
これを3時間ごとに調査となると、1ヶ月で数千万行になってしまって現実的ではありません。
なので調査ごとの変化は1割にも満たないので差分の登録の仕方や利用の仕方を勉強したいのですが、
そのような設計例の載ってる本やサイトをご存知ないでしょうか?
36NAME IS NULL:2010/06/15(火) 21:05:10 ID:???
差分ってか
ようは在庫変動のトランザクションを持ってりゃいいだけの
話のように思うが
37NAME IS NULL:2010/06/15(火) 21:52:45 ID:NSd5kCf1
すいませんもう少し詳しく教えていただけませんか?
単に今の在庫がわかればいいってわけではなくて、
調査日のその時間にどこにどんな値段で在庫がいくらかあったか、店自体開いてたか開いてなかったかなどの
そのままの情報を保持したいので、
在庫変動したら値を変えるだけってわけではないのですが、そういう意味でもしおっしゃられていたのならすみません。
38NAME IS NULL:2010/06/15(火) 22:16:17 ID:???
もし本当にそのままの情報を保持する必要があるなら
30万件だろうがそのまま持っとくほうがいいだろう
ただし、それを保存している間に在庫が動く可能性があるから
その瞬間の在庫という一貫性は保てないぞ

ただし、たとえば保存期間を三日とかにしておく等の制限をつける

三時間おきのデータを数年も保持しとかないといけないとかいうなら
要件を見直すべきかと
39NAME IS NULL:2010/06/15(火) 22:32:03 ID:???
取ったデータで何をするかじゃないかな。
例えばWeb画面でセミリアルタイムで変動をグラフで見せたい(計算させたい)のだったら1クリック5時間のクソアプリになるが、
月に1回バッチで在庫変動情報の帳票を作りたいだけなら全部突っ込んで1億レコードになっても何ら問題ない。
40NAME IS NULL:2010/06/15(火) 22:35:20 ID:???
>>33
てか「(申請に添える)メッセージ」が「(サイト間の)リンク申請情報」を持ってるっておかしくなってるじゃん。
4124:2010/06/15(火) 23:25:43 ID:???
>>40
おかしいですか?
SiteLinkStatusTableにメッセージを置くのもおかしいので
MessageBoxTableにリンク申請情報を持たせてしまえば楽かなぁと
(メッセージ消したらリンク拒否みたいに)
42NAME IS NULL:2010/06/16(水) 01:34:09 ID:???
UserID MEDIUMINT NOT NULL AUTO_INCREMENT
SiteID MEDIUMINT NOT NULL AUTO_INCREMENT
43NAME IS NULL:2010/06/16(水) 10:58:42 ID:1LUS1Pf+
>>38
要件見直すことにします。
>>39
そのクソアプリに近い感じなのでリアルタイムなものと、日間月間変動情報なものとわけて考えて見ます。
44NAME IS NULL:2010/06/18(金) 18:45:41 ID:???
これ見てよ↓
http://livedoor.blogimg.jp/tekepo/imgs/3/4/3414dfca.jpg
ばらまこうぜ!
45NAME IS NULL:2010/06/26(土) 08:48:25 ID:HzXxnfag
最近DBの勉強をし始めたのですが
通し番号 社員ID 社員名 製品ID 製品名 登録日時
のような列があった場合、通し番号 社員ID 製品ID 登録日時のテーブルと他2つに正規化できますが、
検索するときに必ず名を利用する場合(社員名、製品名、登録日時を取り出すのがメインの利用方法)、
サブクエリが増える分検索が遅くなると思うのですが
こういった場合でもテーブルって分けるべきなんでしょうか?
社員ID、製品IDを利用する事はほとんどありません。
正規化するとDB容量は節約できますが、利用時の負荷が増大するのでデメリットに感じます。
それともサブクエリ増えてたとしても、列が少なくDB容量が小さくなるようにした方が速くなるでしょうか?
46NAME IS NULL:2010/06/26(土) 09:23:29 ID:Y5TEab6Q
やってみないと判らないと言われればそれまでだけど、

そんなに心配しないとイケないほど検索が遅くなる?負荷が増える?
47NAME IS NULL:2010/06/26(土) 09:52:42 ID:???
初心者なら型通りにやれ。
パフォーマンスを気にするなら、テーブル設計に手を入れるのはSQLチューニングで
改善の余地があるかどうか自分で判断できるようになってからだ。
48NAME IS NULL:2010/06/26(土) 10:06:21 ID:???
>>45
パフォーマンスのための非正規化なんてのは最後の最後の最後の手段。
社員数が1000万〜1億人もいるならそれもありかもなー、なレベル。
考えるのがムダとはいわないが、悩むのはムダ。
49NAME IS NULL:2010/06/26(土) 10:12:29 ID:HzXxnfag
最終手段なんですね・・・
まずは基本どおりの設計を覚えて経験していくことにします。ありがとうございました。
50NAME IS NULL:2010/07/02(金) 08:29:18 ID:???
>>48
プロフを参照したところこの方、銀歯を作る仕事(プッ)をなさっていたそうで(苦笑)
道理で、物作りの厳しさ、商売の難しさどれを取っても何一つ理解しておらず、突っ込み所満載なわけです
しかも過去形である所を見ると景気に関係なく黙ってても患者が来る、
病気や虫歯を直す商売でさえ勤まらなかったということでは(笑)
銀歯と金型では要求される精度も品質もまるで違います
質問者が何を作りたいのかが明らかにされていないため分かりませんが
趣味のようなもの、とおっしゃるなら趣味の掲示板で相談されたらいかがでしょうか
その分野の同好の士が良い方法をご存じかもしれませんから
もちろん、趣味の世界といえども技術は只で教えてもらえるほど甘い物じゃないという事をお忘れなく
51NAME IS NULL:2010/07/02(金) 12:07:01 ID:???
どこの誤爆?妙に番号だけあってて笑える。
52NAME IS NULL:2010/07/03(土) 11:43:06 ID:magiIcce
enumを使うか、マスタ化するかについて。
http://www.developer0000.jp/2008/11/08/3163/
http://blogs.wankuma.com/ognac/archive/2009/09/07/180928.aspx

全部をマスタ化すると無駄な感じがするのは確かだけど、
表示順や表示名、ロジック分岐フラグなどのパラメータをもてる。
マスタ化しておくことでアプリ内のswitch文を減らすことができる場合
も多々あるので、基本的にはマスタ化が好きなんだけどどう思う?
53NAME IS NULL:2010/07/08(木) 04:33:44 ID:mgDV/kGB
英語⇔日本語
みたいな対応表を作る時のようにどちらも主キーになるような場合は
どちらかを主キーにしてもう片方もインデックスする感じになるんでしょうか?
54NAME IS NULL:2010/07/08(木) 05:47:39 ID:???
別の連番のキーをつけた方がいいんじゃない?
55NAME IS NULL:2010/07/08(木) 16:50:07 ID:mgDV/kGB
>>54
ID 日本語 英語で全部ユニークインデックスってことですか?
IDは使う予定ないのですが将来に備えてということでしょうか。
56NAME IS NULL:2010/07/08(木) 17:37:37 ID:???
日本語と英語はユニークである必要無いんじゃない?
確実に1対1なの?
57NAME IS NULL:2010/07/08(木) 18:05:55 ID:mgDV/kGB
>>56
確実に1対1です。かぶることはありません。
商品名の日本語⇔英語⇔中国語⇔ドイツ語とあるとして
日本語から英語、ドイツ語から中国語みたいに検索したいんです。
58NAME IS NULL:2010/07/08(木) 18:36:57 ID:???
かぶらないって空欄も無いってことか
でも連番のidあったほうがいい気がするなあ
検索対象の項目はそれぞれインデックス作ればいいし
59NAME IS NULL:2010/07/08(木) 19:50:03 ID:???
create table Locale(
LocaleID int,
Language char(3),
Message nvarchar(100)
)
select jpn.Message, eng.Message
from Locale as jpn
inner join Locale as eng
on jpn.LocaleID = eng.LocaleID
and eng.Language = 'eng'
and jpn.Language = 'jpn'

60NAME IS NULL:2010/07/08(木) 19:57:54 ID:???
商品名の対訳表なら、商品の主キー+言語コードで主キーにするな、俺なら
61NAME IS NULL:2010/07/08(木) 20:48:47 ID:mgDV/kGB
>>59 >>60
なるほど。これなら言語増えても列増やさなくて済むんですね。
こういうの自己結合って言うんですね。
自己結合って知らなかったので調べてみます。
いま全く知らない状態だと select Message, Language from Locale where LocaleID = 3
の方が速いんじゃないの?とか
行数増えると結合してるから遅くなるんじゃないの?とか思ってたりします。
62NAME IS NULL:2010/07/08(木) 21:24:44 ID:???
自己結合知らんような初心者がパフォーマンス考えるとかムダだから
63NAME IS NULL:2010/07/08(木) 23:34:03 ID:mgDV/kGB
>>62
はい。ベテランの方々が提示したものが初心者の私が考えるより確実にいい設計だと思うので、
そのまま使おうと思います。
64NAME IS NULL:2010/07/09(金) 00:55:58 ID:???
create table locale (
localeid int,
jpn nvarchar(100),
eng nvarchar(100),
doitu nvarchar(100),
china nvarchar(100)
)
65NAME IS NULL:2010/07/09(金) 01:07:19 ID:???

メンテしやすい
66NAME IS NULL:2010/07/09(金) 01:15:13 ID:???
それはないわ
67NAME IS NULL:2010/07/09(金) 01:27:27 ID:???
俺はその形大好きだがw
68NAME IS NULL:2010/07/09(金) 01:38:57 ID:???
>>66
なんでないと思うのかな。必ず全部の言語のデータを一対一で作るという前提なら、ありだろ。
69NAME IS NULL:2010/07/09(金) 03:42:13 ID:???
だってdoituだよ?
70NAME IS NULL:2010/07/09(金) 11:37:32 ID:???
>>66
将来にわたって言語の追加変更削除がないことが担保されるならありだと思うが
71NAME IS NULL:2010/07/10(土) 00:23:34 ID:???
add columnしとけ。
72名無しさん@そうだ選挙に行こう:2010/07/10(土) 10:24:04 ID:???
>>64
要件変更時に悲惨なことになりそうな予感しかしない。
73名無しさん@そうだ選挙に行こう:2010/07/11(日) 10:24:03 ID:???
chinaだけちゃんとしたフルネーム
74名無しさん@そうだ選挙に行こう:2010/07/11(日) 10:25:47 ID:???
あ、フルネームって前に付くあれは無しで
75NAME IS NULL:2010/07/12(月) 22:21:49 ID:???
ごく基本的なテーブル設計の話なんですが。

例えば「プレイヤーは複数の村を所持、村は複数の家を所持する」場合って

こういうのが↓依存リレーションで
playerテーブル:primary(player_id), player_name, ...
villageテーブル:primary(player_id, villege_no), village_name, ...
houseテーブル:primary(player_id, villege_no, house_no), house_name, ...

こういうのが↓非依存リレーションって言うんですよね?
playerテーブル:player_id(primary), player_name, ...
villageテーブル:village_id(primary), player_id(foreign), village_name, ...
houseテーブル:house_id(primary), village_id(foreign), house_name, ...

どちらを採択すべきか、っていうのは何を基準に考えたらいいんでしょう?
(もしくはどちらでもない別のがあるとか)
雑談程度に前者の設計について話してたら「20年前の設計だろ」なんて言われてしまって
ちょっと気になっています。(その人は言い捨てて消えてしまったので聞けない)

またそれぞれのメリットデメリットなんかもあれば教えて頂きたい
(もしくは参考URLでも)。わりと調べたつもりなんですがイマイチいいのがHitせず。
76NAME IS NULL:2010/07/12(月) 22:27:59 ID:???
実際に両方で作ってみたらいいじゃん。
どっちもhouse_name village_nameを何度も書くはめになることに気づくよ。

それでもいいんだ!っていうなら1テーブルで作っちゃえばいいと思う。
「いちいち」player village houseを分ける必要ないでしょ。
7775:2010/07/12(月) 22:29:29 ID:???
あ、各テーブルの関係は1:Nです。情報後出しで申し訳ない。

あと設計のケースとして一個忘れてた、
player, player_villege, villege, villege_house, house と作るケース。
なんて呼ぶのかわかりませんが。

一応自分の考えを書いておくと、
1:Nで、それこそ子の存在が親の存在に依存する場合は依存リレーション、そうでなきゃ非依存
ってだけの話かと考えているのですが。古いとかじゃなくて。

↑に追加で書いたのは、N:Nのときに使う、と。
(逆に言うと1:Nのときに使うメリットは特に無いと思う)
78NAME IS NULL:2010/07/12(月) 22:32:53 ID:???
ごめん見落としていた。
>>75の後者って、一つの村は一つのユーザしか所有できないという制限になると思うけど
それはそういう仕様?
ならそれでもいい。

前者は正規化すべき対象がある(かつ、それが煩雑になりすぎない)のに
やらないというところが20年前なんじゃないかな。
7975:2010/07/12(月) 22:45:14 ID:???
>>78
そこは(遅れましたが)1:Nなので仕様です。

前者のほうが、「家IDから所有プレイヤーを逆引きするのが楽」だとか、
「親が存在しないのに子が存在しうる」といったデメリットがありますが
それでも後者にすべき?

今挙げた二つのデメリットは、最悪冗長なカラムを持つとか、
制約をしっかり設定すればいい話だけど…
パフォーマンスとしては前者の方がいいような気がするのですが。

…いや、それこそ両方組んで実データぶっこんでテストしなきゃわからないか。
結局どちらが是かは要件次第、なのかなぁ。
80NAME IS NULL:2010/07/12(月) 23:07:09 ID:???
1:Nなら前者にする必要がないんじゃ?
> villageテーブル:primary(player_id, villege_no), village_name, ...
に、unique(village_no)をつけて1:Nであるとアピールしてもいいけど。

「親が存在しないのに子が存在しうる」
これを避けたいなら外部キー制約でいけると思う。

パフォーマンスはこの情報だけだと環境によるとしかいえないかと。

あと、誰も所有していない村や家はどうなるの?
8175:2010/07/12(月) 23:25:03 ID:???
あれ、俺疲れてんのかな…

よく考えたら子があるのに親がないリスクは前者も後者も同じですよね。
とにかくこれは制約でどうにでもなると。

誰も所有してない村や家は存在してはいけないので削除…いや、
件数がかなり多い(数千万レベル)のでdelete_flag式にするから制約できないや。
そこはPGの責任でしっかり組むことにします。

やっぱり前者に拘る理由は「逆引きが楽」くらい?
indexによる検索性能…も正しくIndex作れば同じ?か?
だんだん「そもそも依存リレーションの存在価値って何」って考えになってきた。

ちなみに質問では親ー子ー孫の3層にしましたが実装は4層。
前者にするとキー長が長くなって検索にはむしろ不利なのか?
82NAME IS NULL:2010/07/12(月) 23:35:48 ID:???
後者は外部キー制約あるんだから、家があるなら村はあるはずだし、
村があるならプレイヤーはいるはずになっているよ。

キーが長くなるというか、インデックスが肥大化するんでないかね。
そのへん詳しくないけど。

依存リレーションという言葉も知らなくてなんだかごめん。
83NAME IS NULL:2010/07/12(月) 23:42:05 ID:???
で、今依存、非依存について調べたわけですが、

前者は存在しないplayer_idをvillageに登録できるし、
villageがなくともplayerを登録できるので、互いに非依存

後者は>>82で書いたように、playerがいなければvillageに
登録できないが、villageがなくともplayerは登録できるため、
villageはplayerに依存し、playerはvillageに非依存である

ということなんじゃないのかなーと。
84NAME IS NULL:2010/07/13(火) 00:03:57 ID:???
PG的には村や家に確実にユニークなIDが振られてる方が楽だと思うが。逆引きするにしても。
「前者のvillege_noやhouse_noも実はユニークなんです(キリッ」なら糞設計と呼ばれても仕方ないと思うけど。
85NAME IS NULL:2010/07/13(火) 00:16:17 ID:???
どう考えても後者の設計だな。前者のが古いかどうかは知らないが、親子関係が変更になった時に主キーに触らないといけないのが気持ち悪い。
8675:2010/07/13(火) 00:47:25 ID:???
うーむ…。よし、ここは経験と思って、後者で実装することにします。
すでに前者で組んでる最中の、取り返しが付かない段階のシステムがあるので、
違いを肌で感じることにします。

ありがとう御座いました。肌で感じたあとブログにでもまとめようと思います。
87NAME IS NULL:2010/07/13(火) 00:52:30 ID:???
てかもっと新しい(?)というか安全なのは、「プレイヤー-村」関連テーブルと「村-家」関連テーブルを別途作ることじゃないかね。
8875:2010/07/13(火) 00:58:41 ID:???
>>87
それが>>77で追加したやつのことなんですけど、
N:Nならそうせざるを得ないとして、
1:Nでもそこまでします?

その形にすると、子要素1件の増減につき必ず2テーブル触らないといけないので
パフォーマンスが気になります。

1:Nなので、「プレイヤー村」関連テーブルと「村」テーブルの
件数って完全一致で、「なんのために2テーブルに別れてんだ?」って考えてしまうのですが。
89NAME IS NULL:2010/07/13(火) 01:16:13 ID:???
その程度でパフォーマンスが気になるほど更新が頻繁なのか?
9075:2010/07/13(火) 01:30:31 ID:???
更新はそれなりに頻繁、件数が億単位を想定。
パフォーマンスのために多少の開発効率を落とすのも辞さないレベル。
91NAME IS NULL:2010/07/13(火) 01:34:22 ID:???
んな条件を後出しすんじゃねぇよwww
億単位レコードのテーブルは非正規化されてる方が普通なくらいだろw
9275:2010/07/13(火) 01:41:34 ID:???
で、ですよね。すいません。

それを先に出すべきとか言うところに頭がピンと来ない人間が
億単位システムのDB設計をしているという…。
93NAME IS NULL:2010/07/13(火) 01:43:50 ID:???
ていうかそれ何のDB?
9475:2010/07/13(火) 01:53:46 ID:???
MySQLです。

まぁ最初はよほど負荷が見えてるところ意外は基本的に正規形で考えて
後から発覚した負荷について非正規形にする感じで考えてる。
95NAME IS NULL:2010/07/13(火) 02:29:42 ID:???
それがもしモバゲとかグリーとかブラゲならDB以外にも抑えておかないといけない点がいくつかあるんだけど
その辺は大丈夫なのかね。
9675:2010/07/13(火) 02:37:20 ID:???
そのへんは肯定も否定もしないでおくけど
memcache使うとか基幹システムAPIは極力叩かないとかは抑えてるつもり。
まぁスレ違いにもなって申し訳ないのであくまでDB設計の話を、と。
ご忠告感謝。
97NAME IS NULL:2010/07/13(火) 02:46:23 ID:???
そっか。それなら、だいじょうぶかな。DBも分散を検討してね。
うまく行くことを願っているよ。
9875:2010/07/13(火) 03:59:17 ID:???
MASTER、SLAVEの分散もありました、忘れてました。
あとコネクションを極力短く、少なくとか。状況次第じゃいったん切るとか。

で、報告までに。
「複合キー」とか「サロゲートキー」とかでググりまくったら、
「古い」なんて言われたのもぼんやりと納得できてきました。

階層構造に複合キーを使うなんてのは2秒で否定されるレベル、
といった感じが伝わってきました。
(それでも「必ずしも」ではない、ケースバイケースなんだろうけど)

取り返しがつく今のうちに修正に入ることにします…。
99NAME IS NULL:2010/07/13(火) 10:25:55 ID:???
今どき複合キーはないわ。
オブジェクト指向とかORM(Object Relational Mapping)とか考えるとサロゲートキー一択っしょ。

あと、1:Nなら関連テーブルは不要だね。
100NAME IS NULL:2010/07/13(火) 11:55:11 ID:???
俺なら前者にはしない。
なぜなら、playerが所有しない村も(今は無くとも)存在するだろう(かもしれない)し、家も同様。
また、所有者が変更になるとき、pkeyの更新になるのはいただけない。
101NAME IS NULL:2010/07/13(火) 22:17:58 ID:???
複合キーとサロゲートキーって、
具体的にどう違うの?
102NAME IS NULL:2010/07/13(火) 23:08:29 ID:???
サロゲートは完全なキーであるためだけのキー。
103NAME IS NULL:2010/07/14(水) 13:04:15 ID:???
>>102
単独か複合かは関係ないんですね?
ユニークと同じ意味と思っていい?
104NAME IS NULL:2010/07/14(水) 13:13:29 ID:???
>>103
何で調べないの?
Wikipediaでもある程度わかるのに。
http://ja.wikipedia.org/wiki/%E4%B8%BB%E3%82%AD%E3%83%BC
105NAME IS NULL:2010/07/14(水) 22:43:21 ID:???
サロゲートキーは「本当はいらないはずだけど、どうしても作らなければいけない」
というイメージがあります。
ダミー列がprimary keyのような感じ。
106NAME IS NULL:2010/07/14(水) 22:52:25 ID:???
祇園精舎の鐘の声
諸行無常の響きあり

沙羅双樹の花の色
盛者必衰の理をあらわす

おごれる人も久しからず
ただ春の世の夢のごとし

たけき者も遂には滅びぬ
偏に風の前の塵に同じ

サロゲートキー、それは自然キーの否定。
107NAME IS NULL:2010/07/15(木) 09:22:23 ID:???
>>105
あんたの感想はわかった。それで?
108NAME IS NULL:2010/07/15(木) 11:02:19 ID:???
いやまぁ合ってるよ
業務要件上はいらないけど、システム要件上は必要なので
ダミー(ユニークネスを保証する以外に意味のない)列を追加するわけだから
109NAME IS NULL:2010/07/15(木) 11:14:09 ID:???
まーた始まった
110NAME IS NULL:2010/07/15(木) 21:21:24 ID:???
>>107
ごめんなさい。
111NAME IS NULL:2010/07/18(日) 09:49:29 ID:???
>>109
ん?まーた始まったって?

私は初めて書き込みますが、サロゲートキーは一つのデータベースで必要な部分と不必要な部分があります
必要な部分では必ず適用します
不要な部分では使用しません
何故必要な部分で使用するかというと使用しなかった時に大変困ったという経験則に基づくものです
不要な部分というのはデータベースごとで違うでしょうが、使用しなくても大して困らなかったという経験則に基づくものです
つまり必要無いと思う人は使わなければ良いし必要だと思う人は使えば良いだけじゃないでしょうか
112NAME IS NULL:2010/07/18(日) 14:00:29 ID:???
>>111
「必要なとき使う、不要なとき使わない、その基準は経験則」
そんな情報をネット上のフォーラムに残すことに何の意味がある?誰の参考になる?

どうせならその経験則を少しでも、ほんの一部でも噛み砕いて置いていってくれないか。
113NAME IS NULL:2010/07/18(日) 14:31:12 ID:???
>>111ではないが、RDB的なサロゲートキーってのはその名のとおり長大な
複合キーなど取り回しに難がある場合に代理として用いるものだろ。どのくらいで
「難がある」かはケースバイケース。
ただし、>>108の言うような「ユニークネスを保証する以外に意味のない」キー
というのは本来のサロゲートキーとは違って、OODBのIDのようなもの。
こいつらはデータモデルがそもそも違うんで、ごっちゃに議論すると発散する。
114NAME IS NULL:2010/07/18(日) 15:17:40 ID:???
顧客が決める気持ち悪いコードに対して
それと1対1になるように一見意味のなさそうなIDを振りなおすのがサロゲートキー。
(あとから仕様変更によって、1対1じゃなくなる可能性があるが)

単にテーブル設計の都合上の複合キーに対してIDを振りなおすのは
ちょっとわけが違うということか。
115NAME IS NULL:2010/07/18(日) 15:58:36 ID:???
いや、どっちかっつーとサロゲートキーというのは後者。
また、前者で1:1でなくなる仕様変更というのは、RDB的には「そんな仕様変更があったら
従属関係が変わってるからテーブル定義を変更せずに済むとは限らんだろ」となる。
これが有効なのは、OOあるいはER的に「オブジェクト/エンティティ境界はそれが持つ
属性やその関係よりも安定である」という前提でそのように設計した場合の話。
116NAME IS NULL:2010/07/18(日) 17:20:37 ID:???
サロゲートキーが必要/不必要で論じると、
複合キーを認めないという前提でないかぎり、すべて不必要だと思うが

ただ単に取り扱いが楽かどうかだけの問題以外に必要性があるなら教えてほしい
117NAME IS NULL:2010/08/07(土) 07:48:37 ID:???
ニコニコ動画とかのタグ付けって
ひとつのカラムに空白区切りとかで押しこむのが普通なんでしょうか?
118NAME IS NULL:2010/08/07(土) 09:52:59 ID:???
>>117
動画テーブルと、タグテーブルの間でN:Mの関連を構築すればいいんじゃないの?
119NAME IS NULL:2010/08/07(土) 16:40:59 ID:???
>>118
ありがとうございます
勉強してきます > <
120NAME IS NULL:2010/08/07(土) 20:29:49 ID:???
http://q.hatena.ne.jp/1152280193
仕事でやってるとこんな風に考えられるのか・・・
アマだとまったく思いつかない; ;
121NAME IS NULL:2010/08/07(土) 22:56:44 ID:???
実際の仕事ではpopular_tagsとtagsテーブルは合算されるよ
なるべくテーブル数は減らして結合処理のボトルネックを減らした方が後々いいからね
122NAME IS NULL:2010/08/08(日) 16:59:01 ID:???
減らす為にpopular_tagsを作ってるんじゃ。。
123NAME IS NULL:2010/08/09(月) 00:27:37 ID:???
え?
124NAME IS NULL:2010/08/09(月) 12:04:21 ID:???
数学
125NAME IS NULL:2010/08/09(月) 22:23:38 ID:???
>>121
>なるべくテーブル数は減らして結合処理のボトルネックを減らした方が後々いいからね
やめてくれ
126NAME IS NULL:2010/08/09(月) 22:36:39 ID:???
初心者は結合すると遅くなると本気で信じてる奴いるからな。
127NAME IS NULL:2010/08/10(火) 02:41:55 ID:???
ド素人が第三正規化にこだわるのをよく見るな
128NAME IS NULL:2010/08/10(火) 11:17:30 ID:???
> 結合処理のボトルネック
SQL書けない馬鹿の言い訳
129NAME IS NULL:2010/08/10(火) 12:42:16 ID:???
あるあるw
130NAME IS NULL:2010/08/10(火) 13:30:12 ID:???
>>120
相変わらずhatenaはレベルの低い回答が多いな
131NAME IS NULL:2010/08/10(火) 14:07:34 ID:???
SQL書けない人にJOINさせると開発工数のボトルネックになる(笑)
132NAME IS NULL:2010/08/10(火) 15:46:06 ID:???
>>120をよく読まずに>>121が反応してるので話がかみ合ってないだけじゃね?
popular_tagsはタグの種類じゃなくて集計用のテーブル。
目的は精度や時系列の一貫性を求められないが頻繁に参照されるデータの取り扱いのためであって、
正規化やそれを崩した場合のJOINのパフォーマンス云々は関係ない。
133NAME IS NULL:2010/08/10(火) 18:31:51 ID:???
集計のためのカウントアップの前にjoinする必要がある
結果を表示する時もjoinする必要がある
結論:無駄

おk?
134NAME IS NULL:2010/08/10(火) 19:00:09 ID:???
>>133
だからさ、どういう仕組みのシステムを想定してるかで変わってくるのだから、
その辺を明確にしないと話がかみ合わない。
それぞれ違うものを想定して結論だけをあーだこーだ言っても仕方ないだろ。
135NAME IS NULL:2010/08/10(火) 19:22:10 ID:???
あのさ、普通に考えてみなよ
カウントアップの時はユーザがタグを入力した時
そのタグ名を判定しつつカウントアップしないといけない
つまりjoinまたは過剰なクエリ発行を伴う

結果表示も同じ
タグ名無しで表示される事何てまずない

システムによっても糞もないだろ
id指定でカウントアップする事例ってあるのか?
id表示させて満足させる集計表示ってあるのか?
まともなシステムならねぇだろ

たのむから億単位のレコードを扱ってから物申してくれ
こんな設計をする奴は経験が浅い
136NAME IS NULL:2010/08/10(火) 19:28:19 ID:???
>>135
じゃ一つシナリオを挙げよう。
popular_tagsテーブルはいらない。tagsをgroup byすれば済む。
ただこれを人気タグの一覧を表示するごとにクエリするとコストが高い。
それで10分おき位にgroup byのクエリを行い、popular_tagsテーブルにキャッシュしておく。
場合によってはRDBではなくアプリケーションサーバー内のメモリにキャッシュしてても良い。
137NAME IS NULL:2010/08/10(火) 22:25:31 ID:???
>>121
>実際の仕事ではpopular_tagsとtagsテーブルは合算されるよ
合算って何?
138NAME IS NULL:2010/08/11(水) 00:04:59 ID:???
>>135
ずれてない?
139NAME IS NULL:2010/08/12(木) 16:56:53 ID:???
所与の条件は、タグは自由入力形式で1つのコンテンツに対して複数付けられるってことだよね。
人気タグに関しては検索数(参照数)が多いのか、付けた数が多いのか明確にされていない。
また集計期間を設けるかどうかやその期間についても明らかにされていない。
検索数の場合はカウントアップが必要になるかもしれないが、
付加数ならば>>136の方法が妥当じゃないかな。
>>135の想定しているものがいまいち分からないが、
それぞれのテーブルが1:1:1でとか考えていて、
タグ名と参照数をわざわざ3テーブルに分けるのは無駄だとか考えているのだろうか。
>>136のはコンテンツとタグが1:n、人気タグテーブルが独立して存在という考え方だろう。
140NAME IS NULL:2010/10/14(木) 02:48:47 ID:etNKxQCa
>>127
第三正規化が正確に出来てから言え!!
まずこだわることが大事だぞ。
141NAME IS NULL:2010/10/14(木) 10:25:29 ID:???
>>127のはできないやつのいいわけだからw
142NAME IS NULL:2010/10/14(木) 10:45:55 ID:???
121みたいな何も知らない馬鹿はおいておいて、人気タグのようなケースはデータ構造というよりアプリ依存の話だから、ごっちゃに話すと混乱するでしょ。

データ構造の話でいえば、ちゃんと正規化して最適化されたデータ構造が保持できていれば、人気タグのような集計系によるJOINも問題なし。
いまどきの商用(とほぼ同等品も含む)RDBMSならストアドにすれば高コストと言ってもたかが知れてる。(タグが毎秒何千とかで追加変更されているとかじゃない限りw)
当然、適正に正規化できているデータ構造に冗長なテーブルは存在しない(まぁ、それは理想だがw)。

アプリの話で言えば、WEBアプリのネックはページ生成と通信部分だから、サーバサイドのデータ処理よりこちらのほうが普通はデメリットになる。
なので、人気タグやそのとび先をあらかじめ一定時間毎に静的ページ(厳密には静的ページではなくてもそれと同等の負荷のものも含む)を作成するような場合もある。
検索でインデックスと展開先をあらかじめ作っておくパターン。このような場合は、そのページ生成のためのデータをどこかに当然吐き出すわけだが、
それがテーブルなのかHTMLのようなファイルなのか、とにかく出力先の違いだけ。

hatenaの回答者はそれを一緒くたに回答しているので話がややこしくなってる。
143NAME IS NULL:2010/10/14(木) 14:33:13 ID:???
ナンカワロタw
どんだけ一人の書き込みを気にしてんだよw
144NAME IS NULL:2010/10/14(木) 17:27:43 ID:???
一人の書き込みに食いつかざるを得ないほど、ネタがないw
145NAME IS NULL:2010/10/14(木) 20:57:41 ID:???
アクセスコストがストアドで解決できるとかw
146NAME IS NULL:2010/10/15(金) 00:14:44 ID:???
>>121は、元コボラーだな。

元コボラーが設計したテーブル設計って酷いのが多いんだわ。
147NAME IS NULL:2010/10/15(金) 07:39:41 ID:???
>>145
アクセスコストの話は下段だろjk
148NAME IS NULL:2010/10/15(金) 09:10:34 ID:???
121の人気に嫉妬w
たぶん合ってるから人気なんだろうなw
149NAME IS NULL:2010/10/15(金) 10:19:56 ID:???
2ヶ月も前の話題を引っ張るなよ。それにしても>>121大人気だな。
150NAME IS NULL:2010/10/15(金) 11:14:08 ID:???
いまどき一般的な規模のRDBでテーブルの結合がボトルネックになる、なんて書いたらそりゃ人気も出るw
151NAME IS NULL:2010/10/15(金) 21:55:23 ID:???
>>147
下段って?>>142本人なら解説キボン
152NAME IS NULL:2010/10/25(月) 20:01:40 ID:???
>>146
元コボラーには有償研修のSQL入門程度は行かせた方が良い。
わずかな投資で使いものにならなかった人材が使えるように
なったらもうけもの。

汎用機ではこうだったからだ、、、
と仕事を妨害することも少なくなれば一石二鳥。
153NAME IS NULL:2010/10/25(月) 21:56:18 ID:G/Enqt3S
COBOLにOCCURS項目があるといのがCOBOLとSQLの相性が悪いところなんでしょうかね… w

それだけではないでしょうけど
154NAME IS NULL:2010/10/25(月) 23:29:57 ID:???
SQLというより、テーブル定義の問題だがな
COBOLのようなISAM編成に向いたテーブル定義と
RDBを前提としたテーブル定義は違うってことだ
155NAME IS NULL:2010/10/26(火) 22:28:35 ID:BB4To3r1
ある製品を作る時に使用する部品をDB化したい。

[条件]
1つの製品を作る際に使用する部品の種類は、1個〜20個以内。
データの出力時には、固定列数なフォーマットにする。
--

こういう場合も正規化ってする?
クロス集計でしか利用されないデータを正規化するのってすごい非効率な気がするんだがどうなんだろう。

[非正規化]
作成No,製品名,部品1個数1,単価1,部品2,個数2,単価2〜部品19,個数19,単価19,部品20,個数20,単価20,合計,作成日,コメント

[正規化]
作成No,製品名,合計,作成日,コメント
部品No,作成No,部品,個数,単価
156NAME IS NULL:2010/10/27(水) 00:55:32 ID:???
>>155
将来、部品点数が絶対に増えないといえるのなら、
非正規化でもいいかもね。

将来、部品点数が増えたり、階層化する可能性があるなら、
正規化しといたほうが、後々潰しが効くと思う。
157155:2010/10/27(水) 11:38:52 ID:???
>>156
どうもです。

階層化は考慮外ですが、部品点数が増える事に対しても非正規化の方が
工数的(作成時、実行時ともに)に有利だと思うんだけどなー。

テーブルを修正しなくても良いという点では正規化が優れているが、
それほど加点でもなく、マイナス点の方が多く思える。

Gridに表示させたり、CSVなどで出力したりで毎回毎回別途に集計しなければならないのは面倒くさい。
制限チェックも増えるし、取りだしが必ず2度以上になってしまうからレスポンス的にもだいぶ不利だし…。
皆さんどうしているんだろうか。そういう欠点よりも将来の拡張性の為に正規化をしているのかな。

悩む…。
非正規化はテーブルの見た目がださい所も気になる。
158NAME IS NULL:2010/10/27(水) 12:22:13 ID:???
>>155
非正規化の場合、部品のステータスに修正入ったら一括変更でもするつもりか?
データ構造が変わらない(商品を構成する部品の点数や構成が将来的に変わらない)としても、表示するフロントエンド(アプリ)は色々変わったり、
他の場所で使われることがあるから、素直に正規化しておけ。
非正規化されたデータをもとに他の人間がフロントエンド作るのは非常に面倒くさい。

その程度のクロス集計のコストが高くなるというのは、そもそもの設計か実行時のSQLに問題があるだけ。
159NAME IS NULL:2010/10/27(水) 19:46:30 ID:???
>>157
>非正規化はテーブルの見た目がださい所も気になる。
開発者の感覚としては、これにつきる。
その程度のテーブルなら、どんな構成
でも実行速度は変わらんだろ。

捨てコードでもいいから突貫で、と
いうのでなければ、個人的に非正規は
ありえない。
160158:2010/10/27(水) 19:54:11 ID:???
>>157
非難だけしてもなんなので、現実的な方法を。
仮に出力の(クロス集計の)コストが高いというのが問題であるならば、部品構成の変更などが頻繁でない限りは(今回のケースはそうだと思うが)、
部品の変更や修正、追加をトリガーに出力用のデータをテーブルなりファイルなりに吐き出しておけばよい。
最終形でなくても、計算途中のデータを出力しておけば実行速度の問題はなくなるはず。

大手のデジカメの階層化されたPDMで実際にやってる。
161NAME IS NULL:2010/10/27(水) 23:29:07 ID:???
なんでこうJOIN一発するだけでレスポンスが"だいぶ"悪くなると思う奴がDB設計とかやってるんだろう。
162NAME IS NULL:2010/10/28(木) 00:44:53 ID:???
つかこれ、かならず部品1〜20までを固定で取り扱うというなら
横に1〜20まで並べても非正規化だとはいえない気がする....

が、俺なら絶対実テーブルを部品1〜20まで繰り返したりしない
部品点数が増えたときに非正規化が工数的に有利だと思う考えが理解できん
毎回別途に集計するのがめんどくさいというのも、いまいち理解できん
ビュー使えよ。最近のDBMSなら>160の言うようなワークテーブル的に
使える実体付きビューを使えるものもあるんだぜ
163NAME IS NULL:2010/10/28(木) 12:46:48 ID:2nX/Ozle
テーブル名を日本語で作るのは駄目かな?
164NAME IS NULL:2010/10/28(木) 20:12:37 ID:???
出来るけどやめておけと言われるはず。
日本語が入力出来ない状態でメンテナンスするってなった場合、手段が減る。

特別な理由がない限りASCII文字で作って老いた方が無難。
165NAME IS NULL:2010/10/28(木) 20:23:31 ID:???
どっかで、日本語を推奨してる人を見たことがある。
今はO/Rマッパーやらツールやらがいろいろあり、
テーブル名や項目名を直接タイプすることが少なくなったから、
(日本人しか使わないなら)直感的な日本語のほうがいいとか言ってた。

わりと賛同できるのだが、やっぱ怖いもんは怖いよなぁ。
こんなことで変なリスク抱えたくないわ。
166NAME IS NULL:2010/10/28(木) 21:34:07 ID:???
>>165
>O/Rマッパーやらツールやらがいろいろあり

色々あるから、むしろ TBL0002345 みたいなテーブル名でも最終的にはさほど困らないと思うんだが。
テーブル名や項目名が直感的に把握できる必要があるものに関してはVIEWなりストアドで作ればいい。
167NAME IS NULL:2010/10/28(木) 23:42:40 ID:???
>>165
全く賛同できないんだが。
ていうか、何を言ってるんだ?って感じだ。
そんな奴が近くに居たら、ぶちのめしてやりたい。
168NAME IS NULL:2010/10/29(金) 07:29:40 ID:???
>>167
論理的な意見が聞きたい
169NAME IS NULL:2010/10/29(金) 10:18:23 ID:???
>>168
>>164
>日本語が入力出来ない状態でメンテナンスするってなった場合、手段が減る。
これとか
charset問題とかだろ
170167:2010/10/29(金) 22:55:31 ID:???
>>168
OSやらDBやらアプリやらで、文字コードを統一しないと怖くて使えない。
プログラムを組んでいる最中に、いちいち全角入力モードに変える必要がある。
  (絶対に、全角スペースをコードに記述してしまってコンパイルエラーとなる頻度が多くなる)
半角と全角の区別がつき難い。
  (例えば、"1"と"1"はパッと見解らない。)

あと、O/Rマッパーやらツールやらを使うことが出来ない場合のことを考えろ。
171NAME IS NULL:2010/10/30(土) 05:46:07 ID:???
コンパイルエラーなんて別に構わないだろ。その場で分かるんだから。
怖いのは潜在的なエラーとしてバグを引き起こすこと。しかも数年後とか、改修時に。
後は抽出条件が実は間違っていた、とか。
172NAME IS NULL:2010/11/08(月) 11:58:49 ID:wNBEtH7N
簡単な人材派遣システムを作りたいのですが、空き人材の抽出方法に悩んでいます。

タスクの開始日と終了日、跳び石や繰り返し設定等を組み合わせて検索するには
どうすればいいのか複雑でまとまりません。
単純にタスクを実稼働日の配列として展開し、日付をフラグで
埋めていくほうが明快で良いのかもしれませんが、その場合のデメリットは
あるのでしょうか?

また各人材が稼働日空き日を保持するのと、先に競合タスクを判定して
従事者を除外するのはどちらが一般的なやり方でしょうか?
173NAME IS NULL:2010/11/09(火) 00:22:16 ID:???
業務で人材派遣システムを覗いたことがある。

人のアサインはアサイン管理テーブルみたいなので運用。
基本はDELETE→INSERT、少しでも期間が被った場合はエラー、
前の予約状況をキャンセルしない限り新しいアサインは不可。
174NAME IS NULL:2010/11/09(火) 10:36:25 ID:???
管理テーブルでDeleteは乱暴なので、更新日時が最新なものをピックアップでよい。案件確定後なり一定期間後にログとして出力してクリーニング。
175NAME IS NULL:2010/11/10(水) 11:03:03 ID:zzwY8gI+
>期間が被った場合はエラーについては
どう判定するのでしょうか?

新規側が連続日ならば、
新規期間内に既存開始/終了日のいずれかが無いこと、または
(新規開始前に既存開始があり、かつ新規終了後に既存終了後がある)が無いことで、
競合が無い人物の抽出(または競合するタスクに関わる人物の除外)はできますが、
毎週第二火曜日や、平日土日のみなどの隔日予定が混在するとややこしくなります。

日付に従業フラグを立てる場合は新規開始〜終了までの日数分ループを回して
一日ごとに競合判定することが考えられますが、せっかく規則性あるのに
200日なら200個データを持つのは実用的なのかスマートでないのか…(柔軟にはなりますが)。
176NAME IS NULL:2010/11/10(水) 17:42:59 ID:???
bitフラグ判定で言いじゃん
db問い合わせも出来るし何が不満なんだ?
177NAME IS NULL:2010/11/11(木) 10:54:29 ID:???
給与計算ソフトで「社会保険料等控除後の額」とか
日本語の述語を使いまくった身としては日本語名を支持したい。

文字コードはUnix系では怖いけど.NETならまず心配ないし。
178NAME IS NULL:2010/11/11(木) 12:07:30 ID:???
.NET言語の変数名なら問題おこさないけど
Oracleの列名で日本語はいろいろ問題あるからなぁ
179NAME IS NULL:2010/11/11(木) 20:08:59 ID:???
>>155
>[正規化]
>作成No,製品名,合計,作成日,コメント
>部品No,作成No,部品,個数,単価
遅レスだが

[正規化]
T製品:作成No,製品名,合計,作成日,コメント
T使用部品:作成No,部品No,個数
T部品:部品No,部品名,単価

実はこう?
面倒臭いな
180NAME IS NULL:2010/11/11(木) 23:01:04 ID:???
.NETもLINQが使えないVS2005あたりで開発すると、正規化は諸刃の剣
181NAME IS NULL:2010/11/13(土) 22:34:02 ID:???
>>178
> Oracleの列名で日本語はいろいろ問題あるからなぁ

なんか定期的にこういうやつ出てくるけど、具体的な「問題」とやらは
書かないんだな (w
182NAME IS NULL:2010/11/14(日) 01:25:17 ID:???
最初に入った会社のDB設計は、列名日本語でやってたな。
優秀な人はいたけどガラパゴス状態な感じで、
今になって真似しようとは思わないけど、それなりにちゃんと動いてたよ。
Windowsオンリーの環境だったのが良かったのかもしれんけど
183NAME IS NULL:2010/11/14(日) 10:30:25 ID:???
だから、クローズドの環境なら日本語だろうがドイツ語だろうがハングルだろうがサンスクリットだろうが問題ないんだってばさ。
問題がおきれば随時つぶせばいいだけだし。

環境が頻繁に変わったり、他との連携で様々なドライバ使う可能性があったり、フロントエンドがガンガン増産されるような環境なら、
動作保障内でやるのが定石。
184NAME IS NULL:2010/11/14(日) 13:34:39 ID:???
それ Oracle の問題じゃねーだろ。

そもそも動作保証云々以前に「環境が頻繁に変わったり、他との連携で
様々なドライバ使う可能性があったり、フロントエンドがガンガン増産
されるような環境なら」日本語なんか使う奴は馬鹿だろ。
185NAME IS NULL:2010/11/14(日) 23:41:47 ID:???
>>181
文字コードの問題があるだろ。
日本語にしてしまうことで、文字コードがEUCなのかUTF8なのかSJISなのかを気にする必要が出てくるんだよ。

Windowsならまだしも、UNIX上からSQL文を叩くのに日本語入力することなんてありえねぇわ。
186NAME IS NULL:2010/11/15(月) 00:27:52 ID:???
そんなん今時utfやん。
大体おまえんとこは実機で直接SQLたたいてんの?w
187NAME IS NULL:2010/11/15(月) 08:42:27 ID:???
>>185
何年前の話をしてるんだ?
188NAME IS NULL:2010/11/16(火) 02:10:00 ID:???
わかるわかる。ASCIIのDDLもってけばどんな環境の上でも構築できるよねwww
189NAME IS NULL:2010/11/16(火) 10:57:26 ID:???
試さずに聞くが、NLS_LANG=Japanese_Japan.UTF8でDB作れば
「avとかを列名に含めても問題起こさないのか?
場合によって""で括る必要があったりなかったりで面倒なんだが・・・
190NAME IS NULL:2010/11/16(火) 19:09:37 ID:???
何か問題を起こしそうな文字コードなの?
191NAME IS NULL:2010/11/16(火) 20:42:16 ID:???
>>189
問題ない。



と言われれば信じるのか?w
192NAME IS NULL:2010/11/16(火) 21:32:01 ID:???
>>191
それ、頭悪いレスの筆頭候補だと思ってる。
193NAME IS NULL:2010/11/17(水) 01:07:34 ID:???
>>186
OSはUTF8で、DBはSJISの環境が多いだろが。
勿論、実機でSQL文を叩くことが多いね。
194NAME IS NULL:2010/11/20(土) 14:12:23 ID:sSrpbL1f
DBがSJIS
195NAME IS NULL:2010/11/20(土) 14:47:12 ID:???
OSがUTF8でわざわざDBをSJISにする理由がないだろw
一昔前はOSがEUCでDBがSJISなら結構あったと思うが。
196NAME IS NULL:2010/11/21(日) 22:27:34 ID:4MhMQRH6
得意先別の締日を登録する場合,例えばデータ型をIntとした場合,
月末締めはどのように表現するのがいいのでしょうか?
よく,月末は99として登録するなどのテクニックがありますが,
どのような方法がいいのでしょうか。
197NAME IS NULL:2010/11/22(月) 20:47:59 ID:???
31でいいと思うんだが
198NAME IS NULL:2010/11/22(月) 21:18:08 ID:???
31だと末尾を指定したかったのか31日を指定したかったのかが読み取れない
199NAME IS NULL:2010/11/22(月) 21:26:58 ID:???
31で十分
なんかの時のbitフラグ使用時もちょうどいいしな
99とか今時あるのか?
200NAME IS NULL:2010/11/22(月) 21:30:15 ID:???
それを区別する要件があるなら違う値にすればいい
俺にはそれを区別する要件は思い浮かばない
31日締めの指定って、2月とか4月とかの締めどうするんだ?
201NAME IS NULL:2010/11/22(月) 22:01:29 ID:???
>>200
2月や4月の時に32指定だったら末日だとわかる。
31だとユーザや別システムの入力ミスかもしれない。
202NAME IS NULL:2010/11/22(月) 22:08:29 ID:???
31=月末
入力ミスとかDBでやるならトリガーで見張れよ
基本だろ…
203NAME IS NULL:2010/11/22(月) 22:34:58 ID:???
>>201
それは入力ミスってるんだから別問題だろ
そんなの救ってやる必要ないと思われる
たまにそういう仕様外の動作をコードでキャッチしようとする奴がいるけど
問題の切り分けができてない
204NAME IS NULL:2010/11/22(月) 22:37:36 ID:???
>>201
入力ミスって、32でも入力ミスの可能性はあるわけだが?
結局31でも32でも、その月の末日で締めるわけだろ
わざわざ31日締めという、月末締めとは別の状態が必要か?
それを正しく区別する設計というなら、指定日ごと締めと、月ごと(月末)締めの
締め区分みたいなものを別途用意するのが正解だろうな
205196:2010/11/23(火) 22:38:58 ID:wQ8I8TMH
多くのレス有難うございます。31を月末締めとすればいいようですね。
206NAME IS NULL:2010/11/24(水) 00:22:54 ID:???
>>205
いやー、仕様を確認したほうがいいと思うぞー
そもそも29日締めとかって設定も入るようにする気か?
その場合2月とかどーすんだよw
本当は1日と15日と末しかねーんだろ?
もしくは日付+例外条件とかなってたら日にちで保存はヤバイかもしんないんだぞ
俺が前までいた会社は月の最期の営業日が締め日(技術者向けの)だったぞ
ただし、四半期の月じゃねーときは次の月のはじめの営業日までがセーフ・・・とかそんなんだ
複雑だろ?w

もっと実務について詳しい担当と話合えよw
こーゆーのってディスプレイといくらにらめっこしててもダメだと思うぜ
207NAME IS NULL:2010/11/24(水) 00:39:33 ID:???
それ、締め日じゃない何かと勘違いしてないか?
セーフとかなんだそれ。
208NAME IS NULL:2010/11/24(水) 05:20:01 ID:???
仕様を確認した方がいいのは確かにそうだが
>206の話は締め基準日と、稼働日とか絡んだ実際の締日は別ってだけの話だ
今問題にしてるのは、締め基準日が月末の場合にどう保持するってだけの話
そっから実際の締め日をどう算出するかはまた別の話
209NAME IS NULL:2010/11/24(水) 17:56:36 ID:???
仮に締め日が来月の1日だったときって日付保存ってダメじゃね?って言ってほしいの?
210NAME IS NULL:2010/11/24(水) 18:09:48 ID:???
>>208
すでに実務として1〜31日って指定のが珍しいのに
これを継続して使うのってどうだろ?
よくある締め日と多少の例外ぐらいはサンプル集めたほうがいいと思うね

1日(先月分)、15日(先月16日〜今月分)、25日(先月26日〜今月25日分)、月末(今月分)

だったら折角1〜31日まで入るようにしてあっても大半が無駄なわけじゃん
もうステータスでいいんじゃないの?
ステータスなら第二金曜日とか対応できるよ
211NAME IS NULL:2010/11/24(水) 18:21:48 ID:???
わかった!varchar型にして末日だったら「末日」って登録すればいいんじゃないかな?
212NAME IS NULL:2010/11/24(水) 18:31:52 ID:???
もう割り切って、テキストにすれば。
213NAME IS NULL:2010/11/24(水) 19:52:36 ID:???
>>211
素直が一番ってのは俺の長年のPG経験で学んだこと
214NAME IS NULL:2010/11/24(水) 23:03:51 ID:???
ある売上が何年何月の第何週に起算されたものか、って言うのをシステム上で
表示して欲しいとか言われて、馬鹿正直に作ったら、
お盆期間は必ず8月の1週めに含む、とか、年末年始は〜
とか色々なルールがあって結局全部コードに書いて何とかした。
今も動いてるのかなぁ、あのシステム。
215196:2010/11/24(水) 23:16:33 ID:vMmyFVn7
意外に盛り上がっているので,ちょっと驚いています。

マジレスすると,都度請求なので,単に得意先の締め日がわかればいいだけなので,
あまり複雑には考えていませんでした。確かに,複数の締め日があったり,
締め日が変動するケースもありそうなので,まじめに考えると頭が痛いですね。
216NAME IS NULL:2010/11/24(水) 23:17:29 ID:???
売り上げの起算日とお盆期間がどう関係あるのかよく分からないや。
今年だったら、8/1-8/7がお盆になるとして、8/3の売り上げはそのまま
8月の第一週に起算されたものなんじゃないの?
217NAME IS NULL:2010/11/24(水) 23:43:33 ID:???
こういう仕様は日本のSヨの飯のタネだからな。
218NAME IS NULL:2010/11/25(木) 00:59:50 ID:???
いやだから8/13〜15に立った売上は8月第一週換算とかそんな感じ。
8月12日はお盆期間じゃないから第二週換算だけど、とか。
219NAME IS NULL:2010/11/25(木) 02:30:12 ID:???
あ。
お盆期間を8月1週とする、かと勘違いしてたorz
スマンカッター。

>>217
サマータイムとか旧正月とかあるし日本に限らないような気も。
220NAME IS NULL:2010/11/29(月) 17:50:54 ID:???
得意先マスタに訪問履歴1、訪問履歴2、訪問履歴3というカラムが。
何がしたいのか聞いてみたら、1回目の訪問時の内容を〜、とのこと。
俺「3回以上訪問したら。。。?」
相手「その辺は運用で何とかします。大抵は3回分保持できれば十分ですので。」
だとさ。
221NAME IS NULL:2010/11/29(月) 19:39:04 ID:???
>>220
なんとでもなるのに何を難しく考えているんだろうな?w
素直に訪問履歴xN回になっても大丈夫なように作ってくれって言えばいいのにw
222NAME IS NULL:2010/11/29(月) 20:59:11 ID:???
履歴とかいうから全部残さなくていいのおおおお?と思っちまうけど、要は「初回3回までの訪問日時」だろそれ。
最初の数回の挨拶とか紹介だかの日時のメモ書きであって、4回以上は捨てて問題ないってこと。
RDBとしてはうんこだけど実運用考えればそれはそれでありだろう。
223NAME IS NULL:2010/11/29(月) 23:16:49 ID:???
ほんとにメモ的な情報で良ければそれでもいいのだけど、
あとからとんでもなく重要な情報であることが発覚して、
大改修を迫られることになる。
さらに下請けの悲しさか費用は込みこみで;;
224NAME IS NULL:2010/11/29(月) 23:29:58 ID:???
大改修よりも運用で何とかしていたものを移行するのが死にそう。
過去データ登録機能を作って客に入れてもらうかw
225NAME IS NULL:2010/12/02(木) 01:57:55 ID:???
SQL質疑応答スレから誘導されてきました。
http://hibari.2ch.net/test/read.cgi/db/1274791771

PHP+MySQLなんですが、できるだけDBで処理しようと思っています。

お買い上げに応じて、n%分を顧客にポイントを付与します。
これにはキャンペーンが存在して、水曜と日曜はポイント5倍、
7の付く日(7日、17日、27日)もポイント5倍、1日はポイント10倍などあります。
1日が水曜日の場合は、倍率の大きい、ポイント10倍が適用されます。
また、たとえば、クリスマス期間12月01日から12月26日まではポイント「さらに」1.5倍、三が日は一律10倍などもあります。

こんな感じで、キャンペーンの曜日や期間、パーセンテージを自由に設定できるようにしたいです。
来月からは、水曜はポイント10倍にしよう!なんてのもありえます。

よろしくお願いします。
226NAME IS NULL:2010/12/02(木) 02:14:52 ID:???
追加です。あんまり関係ないかもしれませんが。
先月の購入金額に応じて顧客にグレードがあり、
1万円以上の購入者は基本ポイントがn+1%、
5万円以上の購入者は基本ポイントがn+2%などとなります。
これもDBに格納させたいです。
227NAME IS NULL:2010/12/02(木) 02:40:04 ID:???
いや
肝心のなにが聞きたいのかがわからんし
228NAME IS NULL:2010/12/02(木) 03:51:09 ID:???
どういったテーブルの設計をすれば最適か伺いたかったのですが。。。
229NAME IS NULL:2010/12/02(木) 04:02:27 ID:???
「倍率が高いほうを優先」と「さらに」の2パターンしかないのかな。
230NAME IS NULL:2010/12/02(木) 04:08:27 ID:QCxu6itD
>>225
せめて誘導元の議論ぐらい貼れよ

656 655 [] 2010/12/01(水) 19:43:16 ID:0WLtPE6T Be:
現状、
・日別キャンペーンテーブル
・曜日別キャンペーンテーブル
・期間キャンペーンテーブル
とバラバラに作って、PHPで処理しています。

1か月分のパーセンテージ一覧を作るのに、1日ごとにSQLを複数実行して
かなり重いので、その辺も簡略化できる設計だと助かります。

657 655 [] 2010/12/01(水) 20:21:55 ID:0WLtPE6T Be:
自己レスだけど、こうゆう場合は
カレンダーテーブル(日付、計算済み%をカラムに持つ)を作ってあげて、
各種キャンペーンテーブルを更新するたびに1か月分とかカレンダーテーブルを更新する設計がいいんだろうか?
それだと、売り上げの度に%を取得するのが1回のSQLで済む。
ただし、時間帯別のキャンペーンが作れない(作りにくい)のと、設定忘れなどで、昔の期間にキャンペーンを設定するのが面倒な点が変わらない。。。

658 NAME IS NULL [sage] 2010/12/01(水) 20:43:49 ID:??? Be:
ビュー作れ

660 NAME IS NULL [sage] 2010/12/01(水) 21:01:28 ID:??? Be:
曜日があるからビューはかなりムリゲーだったわ・・。

1,2,3-31の日付だけ持つダミーテーブルを作って指定月の一ヶ月の一覧を取得するSQLをまず作る。
(SQLは多少メンドクサイが)単純な計算なのでこのまま使っても重いとは思えないが、
もし重ければ>>657の通り、月初なりキャンペーンテーブル更新時なりに別テーブルにinsert 〜 select すりゃおk

661 NAME IS NULL [sage] 2010/12/01(水) 22:05:00 ID:??? Be:
キャンペーンごとのテーブルが必要な理由が分からない
カレンダーだけ作ってバッチ更新でいいだろ

663 NAME IS NULL [sage] 2010/12/01(水) 22:10:19 ID:??? Be:
>>661
そのバッチは何テーブルを見て更新するつもりだ?

665 NAME IS NULL [sage] 2010/12/01(水) 22:28:26 ID:??? Be:
>>663
そんな変なキャンペーンルールなんかバッチ側にもてばいい

666 NAME IS NULL [sage] 2010/12/01(水) 22:48:24 ID:??? Be:
>>665
例えばドトールのような不定期なキャンペーンを展開してるシステムとかどうするんだよ間抜け
毎月バッチリリースすんのかよw

667 NAME IS NULL [sage] 2010/12/01(水) 22:55:45 ID:??? Be:
水曜日のパーセンテージ変えようぜってやったら指定日以降の水曜日だけ変わってほしいよねきっと。
今曜日キャンペーンテーブルに期間もたせてるの?ないなら持たせないといけないんだよねぇ。

カレンダー的なメンテナンス画面作るのが楽だと思うなぁ。

668 655 [] 2010/12/02(木) 00:26:41 ID:u5kOJKQ0 Be:
曜日キャンペーンに期間は必要ですねぇ。
いまはまだ付けてないです。
参考にさせていただきます。

それでは、スレ違いだったようなので、別スレにて再度、投稿してきます。
231NAME IS NULL:2010/12/02(木) 04:43:33 ID:???
それぞれのキャンペーンで、パーセンテージを「5%に置き換え」「3%加算」「n倍にする」といった種類をつけたいです。

キャンペーンで、決算キャンペーン12月は+5%、クリスマス期間は「さらに+5%(計10%)」「10%に置き換え」といったような、
期間が重複する場合も、期間の範囲が広いほうから狭いほうに順に計算したいです。
232NAME IS NULL:2010/12/02(木) 07:16:56 ID:???
キャンペーンテーブル作って
買い物ごとに適用されたキャンペーンID入れておけばいいだろ
±Xが%なのか○円以上で〜なのかは多分ルールが変わるだろうからその辺は
その都度でいいんじゃね?(f(x)の形)
233NAME IS NULL:2010/12/02(木) 16:41:21 ID:???
複数のキャンペーンが適用される場合は?
234NAME IS NULL:2010/12/02(木) 17:43:45 ID:???
>>233
>>232に対してのレスだろうか。別途テーブル起こせってことじゃないかと思うんだけど、
そもそもの主眼は適用されるキャンペーンを楽に取得することだからなぁ。
235NAME IS NULL:2010/12/02(木) 18:33:50 ID:???
別テーブルかぁ。
12月3日になって、「そういえば今月は決算キャンペーンだと発表してたのに、システムの設定忘れてた」
って場合はどうする?
236NAME IS NULL:2010/12/02(木) 18:50:16 ID:???
いまキャンペーンテーブルは日別、曜日別、期間別の3つに分かれているわけだけど、
これを1つにまとめちゃうスマートなアイディアは無いの?
237NAME IS NULL:2010/12/02(木) 18:53:48 ID:???
まとめればいいじゃん
開始日付,終了日付,キャンペーンID
そういう〜別とかいうのは月次処理でやりゃいい
238NAME IS NULL:2010/12/02(木) 18:55:13 ID:???
発表した時点でキャンペーン情報を登録しておくべきだよねぇ。

忘れてた時どうするといわれても、どちらかというと別テーブルで保持したほうがバッチつくりやすそうには思うぐらいで、
めんどくさい作業が待ってることには違いないかな。
239NAME IS NULL:2010/12/02(木) 18:56:21 ID:???
このスレ質問者はIDを出す文化がないのか、とおもったけど質問スレじゃなかったな
240NAME IS NULL:2010/12/02(木) 19:01:35 ID:???
そもそもDB設計なんざ枯れてるんだから迷う要素なんてないだろ
設計というのも恥ずかしいぐらい簡単
241NAME IS NULL:2010/12/02(木) 19:22:27 ID:???
簡単すぎて書く気にもならないってレスはまだか?
242NAME IS NULL:2010/12/02(木) 19:23:31 ID:???
>>233
複数登録できるようにしたらいいんじゃない?っていうしなきゃダメだな
なんのキャンペーンが適用されてこの値段になったのかわからないとか最悪の結果だ
計算によって%だけ出して会計すませりゃいいって問題じゃないだろ
下手したら脱税で訴えられそう
243NAME IS NULL:2010/12/03(金) 00:26:26 ID:???
売り上げテーブル
+ID
+売り上げ金額
+ポイント額

キャンペーン適用テーブル
+売り上げID
+キャンペーンID

みたいな感じ?
244NAME IS NULL:2010/12/03(金) 01:11:56 ID:???
しらね
どういうDB作りたいのか詳しく知りたくないからよく読んでない
キャンペーンは確実にその日すべての買い物に適用されるとかなるのか仕様がよくわかってない
タイムサービスとかないんだろか?とか結局なんの統計とりたいの?とかよくわかんねーし
やっぱ、この辺は担当者とお話してちゃんと仕様決めないとね

一般的な〜ってないと思うよ
245NAME IS NULL:2010/12/03(金) 02:02:02 ID:???
え、今日ポイントどれくらいつくの?ってのを取得しやすい設計を知りたいんじゃないの?
俺はそれに応じたレスをいくつかしてはいるんだけれど。

統計とか何の話だろうって思うわ。
246NAME IS NULL:2010/12/03(金) 07:27:23 ID:???
>>245
追記で購入金額に応じたポイントまであるんだから全売上の詳細まで管理したいような感じもするけどね
247NAME IS NULL:2010/12/03(金) 07:31:51 ID:???
買い物客ごとにデータを保持しておいたほうがいいね
実運用では商品によってキャンペーン対象外商品がきっとある(でないと転売屋天国になるからな)

まあ、教科書的な答えだけほしいってんならテキトーでいいと思うけどねw
248NAME IS NULL:2010/12/03(金) 09:57:47 ID:???
キャンペーン複数適用するのに
たとえばAキャンペーンが1000円引き、
Bキャンペーンが1割引だったとしたら
正価から1000円引いてから1割引するのか、
1割引してから1000円引きなのか、とかも考慮する必要あるし
もっと仕様を詰めないといけないんじゃない?
逆に言えば仕様が固まればおのずとDBは決まると思うけど
249NAME IS NULL:2010/12/03(金) 09:59:50 ID:???
ああ、値引じゃなくてポイントか
まぁ話としては変わらんけど
250225:2010/12/04(土) 02:47:21 ID:???
>>248
それもPHPコードで決めうちじゃなくて、
計算順をDBに入れて、利用者が設定できるようにしたいですね。
251225:2010/12/04(土) 03:04:53 ID:???
例えば、キャンペーンにプライオリティカラムをつけて、
その順番に適用していくとか。
252NAME IS NULL:2010/12/04(土) 07:05:44 ID:???
結局どこで詰まってるんだか。

> 1か月分のパーセンテージ一覧を作るのに、1日ごとにSQLを複数実行して
> かなり重いので、その辺も簡略化できる設計だと助かります。
3テーブルあって、月次バッチ処理をしているとして、1日ごとに実行したとしても、90回の抽出と30回の挿入だよね。
なんでそんなのが重くなるんだ?
DB今のままでちょっとチューニングしたら終わるんでないの。
253NAME IS NULL:2010/12/04(土) 07:58:31 ID:???
IPアドレスの管理表をおこしたいのですが、IPアドレス毎に、使用者情報、inbound接続ができる
(=開いてる)ポート番号のリストを持たせようと思っています。
使用者情報まではいいのですが、開いてるポート番号の情報はどのように持てばいいでしょうか?

この開いてるポート番号情報は例えば 22,80,443,3024-3054 といった情報になります。
そして、このポート番号情報にからめて「xx番が開いている未使用のアドレス」という検索がで
きるようにしたいと考えています。

扱うIPアドレス数はたかだか1000件も扱えれば充分なのですが、「0-65535(ポート全開)」とい
うアドレスも扱わなければならないので、悩んでいます。

テーブル1(ip_table)
|ID|IPアドレス|使用者情報など|
テーブル2(opned_tcp_port_table)
|ID|ip_table.ID|ポート番号|
と割っておいて、select 時には join してから select する手もありますが、(ポート全開)な
アドレスの扱いがえらいこと(65536行に膨らむ&opned_tcp_port_tableに65536行分入れておか
ないといけない)になりそうで、ここが悩みのポイントです。
254NAME IS NULL:2010/12/04(土) 08:18:26 ID:???
テーブル2
ID ip_table.ID ポート番号下 ポート番号上
1 1 0 65535
2 2 22 22
3 2 80 80
4 2 3024 3054

select ip_table.ID from テーブル2 where xx between ポート番号下 and ポート番号上
255NAME IS NULL:2010/12/04(土) 09:30:17 ID:???
>>254
between何てのがあったと!
それをip_tableにjoinすれば使いたいポートが開いてるアドレス一覧が取れると。

ありがとうございました。
256NAME IS NULL:2010/12/04(土) 12:08:16 ID:???
>>255

開いてる)ポート番号が飛び飛びだったらどうすんの?
257NAME IS NULL:2010/12/04(土) 12:18:45 ID:???
16ビットで表現できるな。
258NAME IS NULL:2010/12/04(土) 15:10:22 ID:???
IPアドレスマスタ
IPAddress(PK) , ValidFlag

IPアドレス使用者テーブル
IPAddress(PK),SeqNum(PK),UserAccount,ValidDate,InvalidDate

こんな感じじゃダメなんか
259NAME IS NULL:2010/12/04(土) 19:14:51 ID:???
給与の締め日と支払い日を管理するDB設計は、どういった形がよいでしょうか?

月ごとに25日締め翌月5日払いとか、
週ごとに締めて、翌水曜日払いとか、
2週ごとに締めて、翌水曜日払いとか。

こういった要件を自由にカスタマイズできるようにしたいです。
260NAME IS NULL:2010/12/04(土) 19:23:23 ID:???
タイプ:月、週、日
締日
支払日

こんだけ
261NAME IS NULL:2010/12/04(土) 19:25:38 ID:???
二週ごと、とか無理だろ。
DBでやるのは無理だから、ビジネスロジックでやるもんじゃね?
262NAME IS NULL:2010/12/04(土) 20:02:41 ID:???
給与の締め日ってどんな感じで色々かわんのかね?
パッケージ向けってつーことかい
263NAME IS NULL:2010/12/04(土) 20:31:05 ID:???
>>256
偶数番号のみ全開とかは泣ける…

>>258
IPアドレスマスタの ValidFlag はもしかして、65536bitのポート開いてる閉じてるフラグ?
264NAME IS NULL:2010/12/04(土) 20:43:27 ID:???
>>253
悩むのは6500万件のテーブルが「えらいこと」かどうか確認してからでいいだろ。
265NAME IS NULL:2010/12/04(土) 20:46:42 ID:???
65536bit・・・ だめだこりゃ。
266NAME IS NULL:2010/12/04(土) 22:41:40 ID:???
>>255
betweenじゃなくても、
ポート番号下 <= xx and xx <= ポート番号上
で同じことになるよ。
267NAME IS NULL:2010/12/05(日) 08:23:47 ID:???
>>259
DBに計算式のスクリプトを直接突っ込んでる
268NAME IS NULL:2010/12/06(月) 01:27:26 ID:???
>>263
ああ、外部公開用WANじゃなくて、クライアントのIPアドレスの話か
ならLANが前提だろからIPアドレスは主キーには出来ないのでFQDN見るしかない
NICの複数差しも考慮しなくちゃいけない

クライアントマシン公開ポートテーブル
FQDN(PK),NicNum(PK),SeqNum(PK),IPAddress,Protocol,StartPortNum,EndPortNum

ユーザーは別テーブルでFQDNと紐付けて、ポートの重複とか論理整合はストアドで取ればいいんじゃね?
269NAME IS NULL:2010/12/06(月) 02:57:25 ID:???
なんだこの展開
270NAME IS NULL:2010/12/06(月) 10:05:28 ID:???
しばらく見てなかったらえらい複雑な展開になっているみたいで申し訳ない。
後出しで申し訳ないんだけど、やりたいアプリは/24程度のFWの裏にいるグロー
バルアドレス持ちなネットワークのアドレス管理なのですよ。
FWでアドレス毎にinboundの接続設定が異なっているので、それの管理用アプ
リに、と思った次第。
基本 アドレス、利用者、開いてるポート番号 の要素を管理しておきたくて、
このネットワークの利用者からは「××番が開いてるアドレスなーい?」とか
「全開のアドレス空いてない?」いう問い合わせが多いので、ポートの状況で
検索というのが要件に挙がったと。

ここまででいくつかアイデア頂いてるので、それぞれ試作して検討してみます。
なので一旦closeということで。
271NAME IS NULL:2010/12/24(金) 18:04:55 ID:CmCii1Ay
誘導されました

記事が著者、カテゴリ、タグとそれぞれ多対多の関係になる場合次のどっちが使いやすい、パフォーマンスがいい、ですか(検索など)?
記事の分類が増えることはなく、著者はただの分類でログイン等は持ちません。

記事: id, body
著者: id, name
カテゴリ: id, name
タグ:id, name
著者関係: 著者id, 記事id
カテゴリ関係: カテゴリid, 記事id
タグ関係: タグid, 記事id

記事: id, body
taxo: id, name, type
taxo関係: taxoid, 記事id
※taxo.typeは著者、カテゴリ、タグのいずれか
http://hibari.2ch.net/test/read.cgi/db/1276247839/888-889
272NAME IS NULL:2010/12/24(金) 23:16:31 ID:???
>>271
前者じゃないかな。あと、気持ちの問題だけど、記事idを先頭に持って行きたい
273NAME IS NULL:2010/12/26(日) 07:58:53 ID:???
個人的にば、一つの事象を一つのエンティティとして切り出すほうが好きなので、前者で作って、
著者名、カテゴリ名、タグ名から透過的に検索するために、taxo関係をビューにするかな。
274271:2010/12/26(日) 15:36:39 ID:xB/ukp6t
>>272-273
ありがとうございます。

> taxo関係をビューにするかな。
これのやり方がわからないんで教えてもらっていいですか?
275NAME IS NULL:2010/12/26(日) 15:56:32 ID:???
>>274
単にJOINしたSQLをビューにしておくっていう意味以上のものはないと思うぞ
276NAME IS NULL:2010/12/26(日) 15:58:15 ID:???
あ、つまり↑の作りの場合のデメリットはテーブルが増えすぎてわけわかんなくなるかも、ってことだから
ビューをあらかじめ作っておこうという嗅覚が働いたという話かと。
277271:2010/12/26(日) 16:11:28 ID:???
テーブル数は気にならないのでとりあえず上で行って見ます。
ありがとうございました。
278NAME IS NULL:2010/12/29(水) 19:53:07 ID:7r5KYmdf
テーブルAのある列の値がXのときだけ、テーブルBに対応するレコードが存在する。X以外では存在しない、
っていう制約がある場合、アプリ側だけで制御してる?トリガーとかでDB側でも制御してる?
279NAME IS NULL:2010/12/29(水) 21:56:30 ID:???
>>278
その制約が破られたときの金銭的損失、瑕疵として損害賠償請求されたときの想定金額次第
280NAME IS NULL:2010/12/30(木) 04:15:29 ID:???
>>278
俺的にはDB側にあんまり制約つけるの好きじゃないんだが
そのDBが一つのアプリ(システム)からしか利用されないならそのアプリで制御する
複数のシステムで共有されるようなDBなら、DB側になんらかの制御を入れる
ぐらいの基準かな
281NAME IS NULL:2010/12/30(木) 09:39:51 ID:???
あるDBが複数のアプリから利用された場合を想定して、DB側でも制御、だなぁ。
とあるシステムで、顧客情報をWebアプリからも登録されるし、
オフラインのFaxやハガキからも登録される、っていうシステム見たんだけど、
オンラインからはメールアドレス必須なのに、Faxなんかには入ってなくって、
オンライン側でバグる、みたいなことが立て続けに発生してた。
282NAME IS NULL:2010/12/30(木) 11:07:18 ID:???
個人的には仕様書がないときにバイナリしか残ってないアプリからじゃなにも分からないけど、
DB側に実装しておいてもらえれば、最悪でも仕様だけは知ることが出来るからDB側で実装してほしい。
283NAME IS NULL:2010/12/30(木) 13:24:19 ID:???
新任の後任者が仕様変更で一方のロジックしか直さず
顧客をブチ切れさせるのが通過儀礼となる図
284NAME IS NULL:2010/12/30(木) 13:27:35 ID:???
そもそもそんな設計が悪い、とか言い出す奴がそろそろ登場する悪寒。
285NAME IS NULL:2011/01/01(土) 06:48:29 ID:ZTfqWojz
・ユーザ情報テーブル(画像1枚)
・店舗情報テーブル(画像複数)

上のような複数のテーブルに、
それぞれアップロードされた画像の情報を持ちたいんですが、どうするのが一般的/スマートでしょうか。
それぞれ画像が1枚だけなら、そのテーブル自体に画像情報フィールドでもつくればいいのですが、
複数の場合があるので悩んでいます。

自分で思いついたのは、
・画像情報テーブル
を作って
そのテーブルに
foreign_id INT UNSIGNED /* 外部キー */
forein_type enum('user', 'shop') /* どのテーブルの外部キーかの値 */
てな感じで、外部キーをもたせつつ、その外部キーがどのテーブルのものかを判断する値も持たせれば
良いかなと思ったのですが、
もっと良い方法ありますか?
286NAME IS NULL:2011/01/01(土) 10:29:45 ID:???
>>285
・ユーザ画像テーブル
・店舗画像テーブル
をもっちゃいけないの?
画像テーブル一つにまとめて画像データすべてに対してなんらかの処理をしたいなら
一つにまとめるのもアリだと思うけど・・・
普通はint情報テーブルとかもたないよねw・・・
287NAME IS NULL:2011/01/01(土) 11:30:36 ID:ZTfqWojz
>>286
それだと、今後別のテーブルにまた画像が必要なときにまた画像テーブルをつくるはめになるので、、、
1つのテーブルに画像情報がまとまっていれば、
そのテーブルに対するモデルさえあれば、
今後どんなテーブルに画像が必要になっても対応できるので、
なるべく1つのテーブルで管理したいんですよね
288NAME IS NULL:2011/01/01(土) 11:48:57 ID:???
画像情報テーブルにユニークなキーがあれば、
それがユーザーのものか店舗のものかは気にしなくていいんじゃない?

何のために、どのテーブルのものかを判断するの?
289NAME IS NULL:2011/01/01(土) 12:05:43 ID:ZTfqWojz
>>288
例えば店舗情報を表示するページで店舗画像を取ってくるわけですが、
画像テーブルの外部キーが店舗のIDなのか、ユーザのIDなのかがわからないためです
290NAME IS NULL:2011/01/01(土) 12:21:08 ID:???
ダメだこりゃ。
291NAME IS NULL:2011/01/01(土) 15:40:51 ID:???
その「画像データ本人」が自分が店舗画像下ユーザ画像なのかを知ってる必要はないよね。
292NAME IS NULL:2011/01/01(土) 18:42:11 ID:ZTfqWojz
>>291
すいません、完全に理解できないです・・・。申し訳ない。

画像データが店舗のものかユーザのものか判断するのは
どのテーブルのフィールドが担うんでしょうか?
画像が必要なテーブルに、
画像IDを外部キーとして保持するとしても、
複数画像に対応できない気がしますが、認識が間違ってますか??
293NAME IS NULL:2011/01/01(土) 19:00:55 ID:???
・画像情報関連テーブル
ユーザか店舗のキー 画像のキー

これでなんか問題あるの?
294NAME IS NULL:2011/01/01(土) 19:04:06 ID:???
>>292
画像がユーザーあるいは店舗に従属するのであれば、ユーザーと店舗の
テーブルを分けた時点で画像の方も分けなければならない。
どうしても画像テーブルを一つにしたいのであれば、手としては2つある。
・ユーザー・店舗の共通エンティティを用意する
→ただし、ユーザー画像は常に1つ、店舗画像は複数可、などは表現できない
・ユーザー―画像、店舗―画像という連関エンティティを別に用意する。
→場合によっては素直にユーザー画像テーブル、店舗画像テーブルの方が簡単
295NAME IS NULL:2011/01/01(土) 21:28:19 ID:ZTfqWojz
>>293
店舗とユーザのIDは別テーブルなので重複する可能性がありますね。わかりづらくてすいません

>>294
> 画像がユーザーあるいは店舗に従属するのであれば、ユーザーと店舗の
> テーブルを分けた時点で画像の方も分けなければならない。
うーんやはりそうかぁ。
素直に
・ユーザ画像テーブル
・店舗画像テーブル
を作ろうかな。

ありがとうございました。
296NAME IS NULL:2011/01/01(土) 21:36:49 ID:???
店舗とユーザのどっちかを判別できるキーにすりゃいいだけだろ
アプリ側からしたらユーザか店舗かはJOIN時に分かりきってるんだから
解決したならもういいけどさ
297NAME IS NULL:2011/01/02(日) 13:20:56 ID:???
>>295
教科書的な作り方なら

・ユーザ&画像関連テーブル(ユーザ識別+画像ID)
・店舗&画像関連テーブル(店舗識別+画像ID)

・画像テーブル

の3つが必要
298NAME IS NULL:2011/01/03(月) 04:07:50 ID:5FnD8U9u
>>297
あ〜こっちのほうがいいですね。
これでいきます!
どうもです
299NAME IS NULL:2011/01/08(土) 17:11:01 ID:???
今Excelに以下のような形でデータを保存しています

A列 保存場所 e.g F:\data\〜\〜
B列 ファイル名 e.g [xxxx] dddddd.doc
C列 作者名 B列ファイル名のxxxxの部分
D列 タイトル名 B列ファイル名のdddddd.docの部分
E列〜G列 ジャンル D列の作品がどういうジャンルに属しているか
H列 コメント

E列〜G列のジャンルについては現在最大3つ(別にそれに縛られる必要はないのですが)で、最低限1つは必ずあります。
H列についてはあれば記載

で、勉強も兼ねてテーブル化しようと思っているのですが。

作者テーブル
作者名
読み
ジャンルテーブル
ジャンル
は思いついたのですが、
メインのデータテーブルはどのように持てば?という事で
教えていただけたら m(_ _)m
※データテーブルにはファイルをバイナリで入れる事はせずA列の保存場所を
持っていれば良いと思っています

300NAME IS NULL:2011/01/08(土) 17:17:20 ID:???
メインは↓みたいな感じでいいんじゃね?

ID、タイトル名、保存場所、ファイル名、作者ID、ジャンルID、コメント
301299:2011/01/08(土) 19:59:44 ID:???
有難うございます
まぁそういう形になるのかなぁと。
それで試しに作ってみます。
302NAME IS NULL:2011/01/09(日) 09:23:28 ID:???
・ひとつの「タイトル」は、3つ(?)の「ジャンル」を持つ
・ひとつの「ファイル」に、「タイトル」はひとつ
・ひとつの「タイトル」で、複数の「ファイル」がある
・「タイトル」が同じでも、別のファイルなら、作者名、コメントは別?

タイトル { タイトルID, タイトル名 }
ファイル { ファイルID, タイトルID, 保存場所, ファイル名, 作者ID, コメント }
タイトルジャンル { タイトルID, ジャンルID }
303299:2011/01/09(日) 10:28:16 ID:???
・ひとつの「タイトル」は、3つ(?)の「ジャンル」を持つ
現在はジャンルを3つにしていますが、3つに限定しないといけない理由は
ないです。ただ最低限1つはかならず持つという事で

・ひとつの「ファイル」に、「タイトル」はひとつ
  タイトルは1つです

・ひとつの「タイトル」で、複数の「ファイル」がある
・「タイトル」が同じでも、別のファイルなら、作者名、コメントは別?

 複数の作者で同じタイトルという可能性はあります。ただしその場合
ファイルは別々ですが。

304NAME IS NULL:2011/01/11(火) 17:00:09 ID:3vuTbP2k
すんごい基本的な事なんだけど、毎回悩む。
たとえば、男、女 の様なマスターが欲しいとき、IDはふった方が良いんですかね?

男、女 をそのままデータテーブルで保存するようにしても欠点が分からない。
容量の削減にはなるとは思うが、クエリなどでわざわざマスターからリンクしなくてもよい
という利点もあるし。

ただ、マスターテーブルが不恰好な気がするが…。


うーん、、
305NAME IS NULL:2011/01/11(火) 17:06:04 ID:???
最近は性別も更新される可能性のある属性ですwww
306NAME IS NULL:2011/01/11(火) 18:10:31 ID:???
マスターの方を変えたらジェンダーフリーすぎだろw
307NAME IS NULL:2011/01/11(火) 18:16:12 ID:???
性別欄が必須でないデータってのもよくある話で、
男性、女性、中性、(未選択)
くらいはあってもよい気がする。
308NAME IS NULL:2011/01/11(火) 18:20:43 ID:???
JISで性別のコードって規定されてなかったか
309NAME IS NULL:2011/01/11(火) 19:23:54 ID:???
男 男性 M Male のように表現がいろいろあるから残念な気持ちになりつつ、男と女の2レコードを作っておくといいんじゃないかな
310NAME IS NULL:2011/01/11(火) 23:41:02 ID:???
>>304
どっちでもいいんじゃない?
プログラム組んでてもそういう問題ってあるじゃない
311NAME IS NULL:2011/01/12(水) 10:09:47 ID:???
>>304
自分の個人的な判断基準は、その値が表示するだけ(帳票に出ればいいだけ)なのか、検索やグルーピングで使うかかな。
後者なら一応IDにしておく。
312NAME IS NULL:2011/01/12(水) 23:24:06 ID:???
二つだから気になるんだ
オカマとオナベもつけておけば気にならない
313NAME IS NULL:2011/01/12(水) 23:55:36 ID:???
>>308
JISは廃止された(はず)だけど、ISO/IEC 5218:2004 はまだ生きてるかな。
314NAME IS NULL:2011/01/13(木) 15:55:10 ID:???
外部テーブルにすれば外部キー制約が使えるが生データだと使えない
検索はインデックス張っておけばIDもvarcharも大差ない。
315NAME IS NULL:2011/01/13(木) 17:26:19 ID:???
キー=データになるんだから外部キー制約は使えるんじゃないか?
316NAME IS NULL:2011/01/14(金) 03:55:41 ID:???
>>314
チェック制約じゃまずいの?
317NAME IS NULL:2011/01/14(金) 08:43:52 ID:???
MySQLはCHECKねえじゃん
318NAME IS NULL:2011/01/14(金) 11:53:52 ID:???
MySQL前提だったとは。
319NAME IS NULL:2011/01/15(土) 12:11:14 ID:???
標準はティムポウェアだよ
320NAME IS NULL:2011/02/09(水) 06:46:45 ID:???
目指してる 未来が違うwwwwww byシャープ
http://twitter.com/junaoki1/status/6553250337656833 
321NAME IS NULL:2011/02/15(火) 06:01:04 ID:???
使用DBはOracleです。

■生徒テーブル
1.生徒NO→表の中で一意かつnullを許さない
2.クラスNO→nullを許さない
3.出席番号→クラス内で一意かつnullを許さない
4.生徒名→nullを許さない

1番にはPK、2,4番にはnot null制約をつければいいとして
3番はどうすれば良いのでしょうか?
322321:2011/02/15(火) 06:08:14 ID:???
解決策として、「クラスNO」と「出席番号」を結合した「クラス別出席番号」という列を作り
ユニーク制約を付けようと思ってます。

もう少しスマートな方法があれば教えてください。
323NAME IS NULL:2011/02/15(火) 06:10:40 ID:???
check制約でもいいと思うけどね
324NAME IS NULL:2011/02/15(火) 06:42:00 ID:???
>>323
チェック制約だと他の列を参照することはできても、他の行を参照することはできないので
要件を満たせないんじゃないですか?
325NAME IS NULL:2011/02/15(火) 07:07:42 ID:???
普通にout_of_line_constraintでunique制約つければいい
326NAME IS NULL:2011/02/15(火) 08:35:30 ID:???
>>325
ユニーク制約は複数列指定できたんですね。
1番スマートな方法ですね。
ありがとうございます。
327デフォルトの名無しさん:2011/02/19(土) 16:24:44 ID:rzbDbHjB
汎用マスタとか名称マスタとか呼ばれてるごった煮管理なOTLTなテーブルって
いまだに現役?
328NAME IS NULL:2011/02/19(土) 16:45:15 ID:???
現役のところ知っているけど
聞いてどうするの?
329デフォルトの名無しさん:2011/02/20(日) 13:11:42.68 ID:???
その手のマスタにもサロゲートキーをつけて、
ジャーナルデータにはサロゲートキーを埋める形にするべきなのか迷ったので。
あと、適用期間をもって世代管理をしているマスタで親子関係があった場合、
子側のマスタには親のコードを要素として持つべきか否かで迷ってる。
330NAME IS NULL:2011/02/20(日) 14:15:42.10 ID:???
サロゲートキーを使っている現場に出くわしたことない。
サロゲートキーを使おうとしていた現場はあったけど、
キーマンの一言「意味わからん」でお蔵になった。
331NAME IS NULL:2011/02/21(月) 16:11:30.78 ID:???
だいたいどのページ見ても、総合的に見てサロゲートキーは良いみたいに書いてあるけど
実際はそこまでサロゲートキーを使ってるところが多くないのはなんでだ?
332NAME IS NULL:2011/02/21(月) 22:04:24.48 ID:???
この間は複合キーの方が自然だからって押し切られたな。
変更に強い->そんな変更はあり得ない。あったらどうせ大改修だから意味がない。
ORMで楽->フレームワーク側の都合で設計するのは如何なものか。
333NAME IS NULL:2011/02/21(月) 22:11:50.75 ID:???
実際なくてもいい類のものだからな。冗長になることで面倒事も増えたりするし。
流行とか嗜好、メンバーのレベルで臨機応変に変えて問題ないものだから、
その押し切ったリーダーや「意味わからん」つったキーマンが無能というわけではない。
334NAME IS NULL:2011/02/21(月) 22:55:57.34 ID:???
>>331
設計上不自然な値がキーになってしまうから直感的に避けられてる
335NAME IS NULL:2011/02/21(月) 23:43:07.58 ID:???
>>332
そこは説明のしかた次第なんだろうけど、条件をつけずに「変更に強い」とか、
あたかも万能みたいに言ったらそりゃ眉唾で見られるだろうな。
336NAME IS NULL:2011/02/21(月) 23:52:10.02 ID:???
>>334
なんか気持ち悪い・・・ってやつか。

webや書籍で、サロゲートキーについて触れてるのないかな?
具体的にテーブルの定義情報がいくつかあって
どこがどうゆうふうに変更された場合、サロゲートキー使ってる場合は
こうゆう手順で改修ができる。

複合PKを使ってる場合は、こうゆう手順で改修を行う必要があるみたいな
具体的な作業内容が見たい。
できれば筆者の経験談を元に書いてるのがいいな。
337NAME IS NULL:2011/02/22(火) 00:24:45.79 ID:???
SQLアタマアカデミー:第3回 テーブル設計のグレーゾーン〜毒と薬は紙一重 (4)サロゲートキーVSナチュラルキー|gihyo.jp … 技術評論社
http://gihyo.jp/dev/serial/01/sql_academy2/000304
338NAME IS NULL:2011/02/22(火) 00:51:45.64 ID:???
サロゲートキーと何でも一括りにするのって良くないと思うんだ。
人工キーを導入するにしても場面場面でその理由は異なるはずで、
そこを個別の事例ごとにきちんと区別して捉えないと、何でも
サロゲートキーマンセーとかいう困ったちゃんが出てくる。

改修に強くするためという理由でサロゲートキーを導入するのは
元々のデータモデルに時間不変な一意キーが無かったからだよね。
この場合サロゲートキーとはいっても元のデータモデルに修正を
入れているし、下手すりゃビジネスフローのところまで戻って
考え直した方が良いのかもしれない。
でも例えばパフォーマンス等の理由で複合キーを回避するために
使うという場合はサロゲートキーを導入するとはいえ、やりたい
こと自体は元のデータモデルと等価なことだよね。この場合既に
正規化されたスキーマに新たにキーを追加することで大抵は
第三正規形が崩れる。そこを意識して制約とかを加えないと後で
ハまる。

流行とかじゃなくて、ケースバイケースで丁寧に検討する必要が
あると思う。
339NAME IS NULL:2011/02/22(火) 15:36:28.74 ID:???
>>337
なぜか図11では開始時点と終了時点のカラムの値が編集されていないが
これだと商品ID001で検索すると2つhitして
一応代理キーの値が大きいほど新しいということである程度わかるが
いつからいつまで001がガムテープだったのかがわからんよね。

さらにこのサロゲートキーの使い方だと、商品IDにユニーク制約付けられないから
アプリでミスったらどうにもならなくなるな。
怖すぎるんだが。

おれんとこは、得意先の合併とかで、得意先マスタの得意先NOの使い回しが行われるような場合に備えて
トランザクションのデータを作った時の名称も同時にトランザクションのテーブルに埋め込んじゃうんだが。
サロゲートキーも使ってない。

■受注明細
商品NO
商品名称
得意先NO
得意先名称
日時

上記のようなテーブルにしといて、検収まで終わった「過去」の受注明細を「参照」するときは
テーブルを結合せずに得意先名称をひっぱってきたりする。
不細工な形だが、わかりやすいんだ・・・
340NAME IS NULL:2011/02/22(火) 16:12:26.97 ID:???
履歴的なテーブルならまぁそういうやり方のとこが多いんだろうね
過去に遡って洗い替えとかあると死ねるけど
341NAME IS NULL:2011/02/22(火) 18:41:41.93 ID:???
ちなみに商品IDの付け替えってありなの?
なにかと面倒だし、大した手間でもないから必ず新しいの作ってもらったほうがいいと思うんだが。

得意先は合併とかあるからお客さんの要望次第って感じだが。
342NAME IS NULL:2011/02/22(火) 20:54:07.27 ID:???
顧客要望によってはないこともない
正確には商品IDじゃなくて商品コードの付け替えだがな
343NAME IS NULL:2011/02/22(火) 21:13:38.22 ID:???
コードの桁数が3桁固定とか決まってる場合はどっかでリセットする仕様な場合はあるね。
ただ3桁のみがキーになることも滅多にないと思うが。
344NAME IS NULL:2011/02/23(水) 04:06:56.64 ID:???
DBは初心者です
テーブルA,Bの関連が1:1?または1:N*なテーブルは、相手が存在しない可能性もあるので
1.AとBに主キーを設定し、テーブルCにAとBの関連を入れる
2.Bの主キーをAの外部キーとして持たせ、Aの外部キーにnull値を許容する
のとどちらが良いと思いますか?

また、他のケースについて、今のところ
1:N*の場合は1を選択
1:1の場合と1:N+の場合は2.でnullを許容しない
N*:N*やN*:N+、N+:N+はA,Bどちら側からも検索する可能性があるなら1のみ(にこ動のタグとか)
そうでないなら検索する可能性がある項目を持つ側に外部キーを持たせる設計も検討する
という指針を考えてるのですが、大丈夫でしょうか
速度よりも修正容易性を重視したほうがよさそうな環境なので、基本サロゲートキーを付けてます
345NAME IS NULL:2011/02/23(水) 05:47:09.64 ID:???
どういうことだ?
346NAME IS NULL:2011/02/23(水) 06:29:33.66 ID:???
>>344
テーブルA,Bの関連が 1..N(Nは0以上) の基本を以下に書くよ。

o テーブルAに主キーを設定し、テーブルBには(テーブルAを参照する)外部キーを設定する。
o テーブルBに主キーが必要か否かは、エンティティA無しにエンティティBが存在しうるか否かで決める。

テーブルBの外部キーとしてNULL値を許容するとか、関連テーブルが必要かとかを検討する必要があるのは、
エンティティAも存在しないこともあるという関連 M:N(M,Nとも0以上) の場合だけだよん。
347NAME IS NULL:2011/02/23(水) 14:48:31.30 ID:???
テーブル名やカラム名にマルチバイトの文字って使う?
とんでもなく長いsqlとか書いてるとわけわかんなくなるから、マルチバイト使いたいような気もするし
もしかしたら今後のアップデートとかでマルチバイトが祟ってエラー吐くかもしれないから
あんまりマルチバイトを使いたくないって気持ちもある。

カラム名はシングルバイトでコメントの部分だけにマルチバイトってありかな?
これなら多少ましにはなると思うんだが、中途半端感が否めない。
348NAME IS NULL:2011/02/23(水) 16:39:26.64 ID:???
オラクルだと結構日本語テーブル日本語カラム見かける気がする
349NAME IS NULL:2011/02/23(水) 19:20:11.70 ID:???
客先でコンソールでデータとろうとしたときに詰むのが怖すぎる
350NAME IS NULL:2011/02/23(水) 19:23:18.26 ID:???
確かにリモートでつなげないような環境でデータを見る可能性があるならシングルバイトのほうが良さそうだね。
俺んとこはそうゆう事は一切ないから気づかなかった。
351NAME IS NULL:2011/02/23(水) 19:37:11.95 ID:iyykSQn2
以前働いていてたとこ、DB名、テーブル名からカラム名まで全て日本語 w
352NAME IS NULL:2011/02/23(水) 19:50:08.25 ID:???
>>351
それで具体的に何が困ったかkwsk
353NAME IS NULL:2011/02/24(木) 02:03:54.85 ID:???
最近の自動生成系の機能がついたIDEなんかだと日本語変数名にもつながっていくので
規約で変数名にマルチバイト文字使っちゃダメとかやると面倒くさい。
逆に積極的にマルチバイトを使うように決めてしまえばあるいは。
354NAME IS NULL:2011/02/24(木) 02:14:58.82 ID:???
MySQLの公式ツールが落ちるからマルチバイトは使わないなぁ
コメントの日本語だけで詰むw

supplier.id ほげ.仕入れid hoge.siireid
こんなDB見た事がある
355NAME IS NULL:2011/02/24(木) 03:46:34.08 ID:???
>>354
MySQLってそんなにマルチバイトに弱いの?

一昔前までは、世界的なシェアで見ると、MySQL>PostgreSQLだが
日本ではMySQL<PostgreSQLだった。
PostgreSQLに比べてMySQLは、最初のころはマルチバイトに弱いとかで人気が出なかったが
だんだんそのへんが良くなって来てるから、PostgreSQLとトントンくらいのシェアになってるとか
どこかで読んだ気がするんだが。

公式ツールで扱えないんじゃMySQLではマルチバイトでカラム名を付けるなんてことは考えられないなw
356NAME IS NULL:2011/02/24(木) 07:27:19.12 ID:???
トントンくらいになったが、PostgreSQLの改善速度がかなり早く、MySQLはまた引き離されてしまった印象。
357NAME IS NULL:2011/02/24(木) 12:17:16.70 ID:???
>>354
公式っても、GUIツールだろ。
そりゃあしかたない。

他は全然安定してるから問題ない。
あんまり。
358NAME IS NULL:2011/02/24(木) 12:43:23.84 ID:???
サポートされてる機能を使っちゃいけないってのもおかしな話だしな
359NAME IS NULL:2011/02/24(木) 16:58:43.49 ID:???
>>357
仕方なくないだろ。
あきらかにマルチバイトは軽く扱われてるじゃん。

OracleやSQLServerですら稀に問題が起こるのに
MySQLで問題が起こらないとは到底思えないな。
360NAME IS NULL:2011/02/24(木) 18:31:35.55 ID:???
マルチバイトのテーブル名だの、項目名だの欲しがるのは、開発側じゃなくて大抵客。
だから、マルチバイトにしたビューを用意すればいいだけ
361NAME IS NULL:2011/02/24(木) 22:29:28.02 ID:???
Oracleだとマルチバイトのカラム名は""で括らないと動かん場合がある
362NAME IS NULL:2011/02/24(木) 23:14:03.56 ID:???
>>361
Oracleで""で括ってないって理由で動かないSQLを1度だけ見たことがある。

SQLServerは""で括らなくても問題ないの?
363NAME IS NULL:2011/02/25(金) 23:38:18.25 ID:???
>>346
ありがとうございます。

>o テーブルAに主キーを設定し、テーブルBには(テーブルAを参照する)外部キーを設定する。
なるほど、これが一番良さそうです

>o テーブルBに主キーが必要か否かは、エンティティA無しにエンティティBが存在しうるか否かで決める。
主キーについてまだ理解が足りてなかったみたいです
では、DB設計時は1:NやN:Nといった関連と、
単体で存在しうるか、という軸でも整理しておく必要があるってことですね
今作っているテーブルの該当部分は親子関係(子がない場合もあり、子単体は存在しない)なので
親への外部キーのみ設定して、子の主キーは設定しなくても良さそうです
364NAME IS NULL:2011/02/26(土) 02:25:39.36 ID:???
>>346, 363

訳が分からない。

> テーブルBに主キーが必要か否かは、エンティティA無しに
> エンティティBが存在しうるか否かで決める

なんでテーブルBに主キーが無くて良いことがあり得るの?

> 親への外部キーのみ設定して、子の主キーは設定しなくても
> 良さそうです

子の主キーも設定する。親への外部キーはNOT NULLで参照する。
そんだけ。あと初心者は気軽にNULL使わない。三値論理を理解して、
その面倒くささを理解してから使うこと。
365NAME IS NULL:2011/02/26(土) 10:04:45.13 ID:???
>>364
>なんでテーブルBに主キーが無くて良いことがあり得るの?

>>346で書いたように「A無しにBが(単体で)存在しえない」場合があるから。
具体的には、エンティティAの属性(attribute)としてテーブルBを表現するケース。

より抽象的に(モデル分析的視点で)、トップダウンな考え方を以下に説明する。

あるエンティティAが存在し、そのエンティティAは複数の属性を持つ。ここで各属性について、
(1) エンティティAがその属性を「ただ一つだけ(only one)」持つのなら、
 その属性をテーブルAのカラム(フィールド)として表現する。
(2) エンティティAがその属性を「いくつか(zero or more)」持つのなら、
 その属性をテーブルBとして表現し、テーブルBには(テーブルAを参照する)外部キーを設定する。
(3) エンティティAがその属性を「たかだか一つ(zero or one)」持つのなら、
 その属性をテーブルBとして表現し、テーブルBには(テーブルAを参照する)外部キーを設定し、
 更にその外部キーにはUNIQUE制約を設定する。

いずれの場合でも、テーブルBは「(単体で存在しうる)エンティティを表現」しているのではなく、
エンティティAが持つ「属性を表現」しているのだから、テーブルBに主キーは必要無い。
366NAME IS NULL:2011/02/26(土) 10:16:03.18 ID:???
>>365
BがAに依存する属性だったとしても、Bに主キーがなければ
その属性を一意に特定することができないってことだろ?
「主キー」の意味するところが違う?
367NAME IS NULL:2011/02/26(土) 10:56:57.58 ID:???
>>366
テーブルBの個々の行(ロウ)を一意に特定する必要があるのなら、
そのテーブルBは(属性ではなく)エンティティを表現していることになる。
もしテーブルBでエンティティを表現したいのであれば、当然のことながら
テーブルBに主キーは必要になるよ。
368NAME IS NULL:2011/02/26(土) 11:18:19.70 ID:???
複数存在するのに一意に特定する必要のない属性って、想像しにくいんだが。
それってたとえばどんなもの?
もしかして、BのエンティティキーをAと独立に持つかどうかという話じゃないのか?
369NAME IS NULL:2011/02/26(土) 12:04:19.62 ID:???
>>368
想像しにくいというのが理解しがたいのだけれど、要望とあれば。
たとえばエンティティAが楽曲や書籍のような著作物であるとする。
この場合、作者(作曲家/作詞家/著者/原作者/翻訳者..etc)は属性であり、
ある著作物に複数の作者が関わることがあるから、複数の属性になる。
370NAME IS NULL:2011/02/26(土) 12:23:57.65 ID:???
いや、問題は「一意に特定する必要がない」ということの方なんだが。
作曲家と作詞家、あるいは作曲家が2人いてもそれらは個々に特定
できなきゃならんのが普通だろ。
主キーを持たないということは、仮に同じ曲に同姓同名の作曲家が
2人いたとして、それを区別する術がないということだ。
371NAME IS NULL:2011/02/26(土) 12:32:11.67 ID:???
>>370
>それらは個々に特定できなきゃならんのが普通だろ。

特定する/しないという判断は、与えられた問題(要求仕様)によって変わる。
「普通だろ」というのは設計者の勝手な意図(思いつき)にすぎない。
もしも特定しなくてもいいという問題であるのもかかわらず一意性を作り込んだのなら、
それは過剰な設計(設計ミス)ということになる。
372371:2011/02/26(土) 12:35:49.91 ID:???
>>371を一部訂正する。

X: もしも特定しなくてもいいという問題であるのもかかわらず
O: もしも特定しないという問題であるのもかかわらず
373NAME IS NULL:2011/02/26(土) 12:40:50.21 ID:???
別に本人が必要ないと思ってるんならいいんじゃない?
こんな頭の固いやつにいくら言っても無駄。宗教と同じ
374NAME IS NULL:2011/02/26(土) 12:48:42.38 ID:???
あらゆるテーブルには主キーが存在しなければならないという考え方が、「頭の固い」発想だと思う。
どちらにせよ、人格攻撃に走ることしかできないのなら、漏れは議論から降りるよ。
375NAME IS NULL:2011/02/26(土) 12:53:18.72 ID:???
だからさ、そんなもの見たことがないからどんな例があるか聞いてみたんだが?
RDBでは主キーがないテーブルも許されるが、設計論としてはリレーショナル
モデルにおいて主キーがないなんてことはありえないし。
376NAME IS NULL:2011/02/26(土) 13:02:13.25 ID:???
>>371
ん?しかし>>346では「エンティティA無しにエンティティBが存在しうるか否かで決める」と言っているが?
377NAME IS NULL:2011/02/26(土) 18:27:05.81 ID:???
あまり読んでないけど、
AなしにBが存在し得ない状況では外部キーが主キーと同じ意味を成すといいたいのかな。
そんなことないけど。
378NAME IS NULL:2011/02/26(土) 19:18:11.77 ID:???
>>375
>だからさ、そんなもの見たことがないからどんな例があるか聞いてみたんだが?

重複を許す(=一意性を保証しない)属性テーブルというのは、普通に存在するよ。
なるべく分かりやすい例を挙げたつもりだし、重複の可否(=一意性の保証/無保証)を決めるのは、
DB設計者ではなく与えられた問題(要求仕様、つまり顧客)であることも書いた。
ここまで説明してもなお、自分は見たことが無い/経験した事が無いので想像がつかないと
言われたら、自分としてはショボーンとするしかない。

>RDBでは主キーがないテーブルも許されるが、設計論としてはリレーショナル
>モデルにおいて主キーがないなんてことはありえないし。

まず、関係論理/関係代数の世界においては、タプルに一意性が存在することを仮定しているから、
タプルの重複はありえない。ただし、残念ながらリレーショナルモデルというのは、
タプルの重複を許す多重集合(マルチセットまたはバッグ)なんだ。だからタプルの重複はありえるし、
従って一意性は必ずしも保証されない。必要であれば明示的な一意性制約の宣言が必要になる。

次に、RDB実装における主キー(プライマリキー)と、リレーショナルモデルにおける主キー
(行の一意性を保証する候補キーの集合)とを混同して理解しているように見える。
379NAME IS NULL:2011/02/26(土) 19:24:09.00 ID:???
>>378の続き)

たとえば>>365の(2)でテーブルBに一意性が必要であるならば、設定した外部キーと候補キー
(例えば作者名カラム)との組(くみ, タプル)に対してUNIQUE制約を設定するのが正しいDB設計。
この場合、外部キーと候補キーの組を「主キーとみなす」。(「主キーを設定する」とは言わない。)

>>364のようにテーブルBへ主キー(プライマリキー)を設定した場合には、RDB実装における
テーブルの一意性は保証されても、リレーショナルモデルにおける一意性(作者名の非重複保証)は
実現できないから、誤ったDB設計であると思う。
380378:2011/02/26(土) 20:12:53.64 ID:???
>>326,327
個別にはレスしないが、二人とも「単体での存在性(エンティティなのか?属性なのか?)」と
「主キーの有無(タブルの一意性を保証するのか?しないのか?)」を混同してるように見える。
381378:2011/02/26(土) 20:15:43.69 ID:???
アンカをミスった。

>>326,327は間違いだ。>>376,377に訂正する。
382NAME IS NULL:2011/02/26(土) 20:18:00.38 ID:???
>>378
そういう一般論を言ったら、Aに関係なくBが存在する場合だって
必ずしも主キーは必要ないってなるんじゃね?
383NAME IS NULL:2011/02/26(土) 20:25:44.02 ID:???
>>380
それを混同したのが>>346だと思うんだが。
384378:2011/02/26(土) 20:36:57.54 ID:???
>>382
それでも良いと思う。どこに(普通か普通じゃないかという)境界線を引くか、という話になるね。

>>383
えーと、>>346で書いた「主キーを設定する」という表現は、すべてDB実装における
主キー(プライマリーキー)のことだよ。それが読み取れないということは、やっぱり混同してるんだね。
385NAME IS NULL:2011/02/26(土) 20:54:52.06 ID:???
つまり「主キー」という言葉には2種類の意味があって、自分が意図していたのは
違う方の意味だとw
>>379では「設定する」と「みなす」なんて言い換えまでしてご苦労なこったな。
386NAME IS NULL:2011/02/26(土) 21:41:24.92 ID:???
小難しい表現の割にはどうでもいい話だったな
387378:2011/02/26(土) 21:44:24.81 ID:???
>>385
えーと、困ったな。言葉の「使い分け」はしてるけど、「言い換え」はしていないつもりだよ。
「言い換え」とは、同じ事柄を別の方法で表現するという意味だよね。

>>346のテーブルAは、RDB実装における主キー(プライマリキー)とリレーショナルモデルにおける
主キー(一意性)が一致しているから「主キーを設定する」という表現をしても誤解されることはない。
それに対して、>>379のテーブルBはリレーショナルモデルにおける主キー(一意性)は存在しているけど
RDB実装における主キー(プライマリキー)は存在しないから、誤解の無いように「主キーとみなす」と
表現方法を「使い分けた」。

日本語って難しいね。
388378:2011/02/26(土) 21:55:30.25 ID:???
>>386

>>379では、「>>363のDB設計は誤りであり>>379が正しいDB設計である」と
言い切っちまっているんだけど、これはそのまま放置しといていいのかな?
それとも、これすら「どうでもいい話」なのかな?

「いいや、....だから>>364が正しい」とか「自分ならこうする」というような
反論/異論を期待してたんだけど....。
389NAME IS NULL:2011/02/26(土) 22:09:32.49 ID:???
彼の言う「主キー」と、「主キーを設定する」という用語は
一般的なSEやプログラマがRDBMS上でのテーブル設計をする際のそれと
意味合いが違うってことです

一般的なRDBMS上のテーブル設計では、そのテーブルの行を個別に識別できる項目(の組み合わせ)を
システム的に指定することを主キーを設定するといい、その指定された項目を主キーと呼びます
そういう意味では、行を識別必要があるする全てのテーブルにおいて、主キーを設定することが推奨されます
つまり、全てのテーブルに主キーがあるべきであると言う主張が成り立つわけです
390NAME IS NULL:2011/02/26(土) 22:11:18.60 ID:???
もうどうでもいい。
T字形の論理編ぐらい、どうでもいい。
391378:2011/02/26(土) 22:14:41.27 ID:???
いけね、また間違えた。

X:「>>363のDB設計は誤りであり
O:「>>364のDB設計は誤りであり
392NAME IS NULL:2011/02/26(土) 22:19:21.49 ID:???
もともと「設定する」と「みなす」を別の意味で使っていたのなら、>>346のテーブルAも
「設定する」と「みなす」場合両方があるわけだろ?
それを誤解がないからと勝手に片方だけ書いたら逆に誤解するわ。

じゃあ聞くけど、もう一度言葉の定義を明確にして>>346を正しく書き直したらどうなるの?
393386:2011/02/26(土) 22:48:50.20 ID:???
>>388
たとえば伝票と明細のケースでいえば
明細テーブルでは行を一意に識別する主キーはいらないってのがお前の立場なんだろ?

それで要件満たせるんなら別に問題ないと思うけど、
普通は明細の各行単位で修正入れたいケースとか必ず出てくるから、
現時点で必要ないように見えても必ず主キーは設定するように俺はする。
それがサロゲートキーなのか複合キーなのかは別にどっちでもいい。

ただ、現時点での要件を満たせるんなら後で修正すればいいだけだから、
別にお前のやり方でも俺はかまわない。
お前みたいなやつを説得するのは経験的に難しいとわかってるから、
機能的に不具合が出ないんなら議論なんかせずに迎合する。

要するにどっちでもいいし、どうでもいい。
394NAME IS NULL:2011/02/26(土) 23:01:47.25 ID:???
>>387
モデルの一意性は存在してるけど実装のプライマリーキーが存在しない状態ってなんだよそれ。
つか、そもそも設計段階でそんなもん考慮するのか?
395378:2011/02/26(土) 23:28:17.16 ID:???
>>389
つまり、一般的なSE/PGのRDB設計とは>>375が言うところの設計論としての
リレーショナルモデルとは意味合いが違うってことなんだな。
だから、>>379のような「主キーとみなす」という表現は普通じゃないってことか。
うん、よく分かった。これからは注意しよう。

ところで、>>364では

>子の主キーも設定する。親への外部キーはNOT NULLで参照する。そんだけ。

とあるのだけれど、この「主キーも設定する」という表現は、自分は
単純に「プライマリキーを設定する」という意味であると(勘違いして)解釈しました。
でも、これは>>389によれば「適切な候補キー(たとえば作者名カラム)と外部キーとの
組合せに対し個別に指定できるよう主キーとして(UNIQUE制約を)システム的に指定する」と
解釈すべきなのかな?

分かっている人には当たり前なのかもしれないけど、>>344,363のような初心者に対して
「主キーも設定する」という短い一文からそのような推測を期待するのは、
ヒジョーに厳しすぎるんじゃないかと思うんですが、いかがですか?(自分も勘違いしたし....。)
いや、それすら「一般的なSE/PGのRDB設計」なら普通なのかな?
396378:2011/02/26(土) 23:29:45.71 ID:???
>>392
>>346を書き直してみた。これなら誤解はしないかな?

>>>344
>テーブルA,Bの関連が 1..N(Nは0以上) の基本を以下に書くよ。
>
>(1) テーブルAにプライマリキーを設定し、テーブルBには(テーブルAを参照する)外部キーを設定する。
>(2) 次にテーブルBにプライマリキーが必要か否かは、エンティティA無しにエンティティBが存在しうるか
> 否かで決める。ここで、もし存在しえないのなら、テーブルBは(エンティティではなく)属性を
> 表現することになるから、テーブルBへのプライマリキーの設定は不要になる。
>(3) 最後に(エンティティまたは属性)Bの一意性について検討する。もしBに一意性が必要とされるなら、
> (1)で設定した外部キーと適切な候補キー(たとえば作者カラム)との複合キーをリレーショナルモデル上の
> 主キーであるとみなし、その複合キーに対してUNIQUE制約を設定する。
>
> (以下は同文なので省略)
397378:2011/02/27(日) 00:12:42.89 ID:???
>>393
いいや、その伝票と明細のケースで言えば、明細テーブルの各行は普通にエンティティだと思う。
だからリレーショナルモデルにおける主キー(一意性)は存在するよ。ただし、RDB実装における
主キー(プライマリキー)は設定せず、(明細テーブルを参照する)外部キーと候補キーとなる
行番号カラムとの組(から成る複合キー)をリレーショナルモデルにおける主キーとみなすという
違いはあるかもしれないけどね。

このケースで属性となるのは、ある行を構成する各桁の値だ。ここで、(>>365で書いたように)
行エンティティがその値を「ただ一つだけ(only one)」持つのなら、その値は行エンティティの
カラム(フィールド)として表現する。ここまでは問題無いと思う。意見が分かれるのはこの先だ。

もしも行エンティティがその値を「いくつか持つ(zero or more)」のなら、その値は
属性テーブルとして表現するものとし、属性テーブルには(行テーブルを参照する)外部キーのみを
設定し、プライマリキーは設定しない。更に、もしも与えられた問題下でその値に一意性が
必要であるのなら(=必要な場合に限り)、外部キーと値の組を主キーとみなしてUNIQUE制約を設定する。

具体的な例を挙げれば、値引きオプション、つまり「論理値の集合」で値を表現するケースになる。
ある行が商品を表現するとして、その商品に対する様々な値引き(優待顧客値引き/個別値引き...etc)を
0個以上の任意の組合せで表現することになるだろう。

この場合、>>393であれば、どのようにDB設計をしますか?やっぱり値引きテーブルにも
プライマリキーを設定するのかな。もちろんそれでも(AP開発に苦労はしても)要求仕様を
満たせるだろうから、どっちでもいいし、どうでもいいんだけどね。
398NAME IS NULL:2011/02/27(日) 00:15:40.50 ID:???
>>396
ふむ。「設定」が>>389の意味だとするならば、言っていることはだいたいわかる。
#本当は「存在しうる」とか「エンティティ」と「属性」の違いなんかは明確ではないが、
#ここではそれを措いても特に問題ない。

その上で反論だ。
(1)1:Nならば無条件でBに外部キーを設定することになっているが、こここそ、Bが
Aから独立して存在するかどうかで変わる部分だろう?そうでなきゃ、対応するAの
レコードが存在するBの外部キーはNULLになってしまう。
(2)一意性が必要かどうかは要件で決定されるって自分で書いていなかったか?
自分は必要ないケースはめったにないと思っているが、どちらにしても、エンティティ
ABの関係とは関係がない。
(3)ここは言葉の問題。候補キーは(1)の外部キーを含む場合と含まない場合が
あるが、どちらにしてもそのまま主キーになり得る。だから、外部キーを含まない
候補キーとの複合キーなどというものは考えなくていい。
399389:2011/02/27(日) 00:22:38.04 ID:???
>>395
>「主キーも設定する」という短い一文からそのような推測を期待するのは、
>ヒジョーに厳しすぎるんじゃないかと

「一般的なSE/PGのRDB設計」ならそう思うのが普通だと思うが
純粋な設計と言うよりは、実装方法論だがな
だからあえてRDB設計とかいう言葉じゃなくて、RDBMS上のテーブル設計って言葉をつかったんだ
400NAME IS NULL:2011/02/27(日) 01:01:50.65 ID:???
>>397
なんか例がおかしくない?優待値引きとか個別値引きとかあるのになんで論理値なの?

それはそれとして、値引きテーブルに一意性が必要ない(=同じ値引きが複数存在してもよい)
と言うことであればそれはそれでありだと思うが、特定の値引きを削除するとか変更するなんて
要件があった場合は一意性が必要となる。
一方で、ここに1商品1レコードの在庫テーブルがあったとする。これはここで言う「属性」には
当たらないと思うが、一意性の要否については上の値引きテーブルと変わらない。
つまり、一意性の要否を判断する上で「エンティティ」か「属性」かは関係ない。
401378:2011/02/27(日) 01:49:22.13 ID:???
>>398

(1) AとBが 1:N の関係であるなら、N側であるBから見ると1側であるAは必ず「ただ一つだけ(only one)」
 存在しているはずだと思います。だから、Bの外部キーがNULLになるケースが想像できないのですが?

(2) まず(2)では(一意性ではなく)存在性について述べているので、自分には論旨が不明です。
 ただし一意性については指摘のとおり、(存在性と同様に)その必要性を決めるのは要件(要求仕様)です。
 この点については、>>396への追加記述が漏れていました。

(3) この候補キーというのは、>>364の「子の主キーも設定する」というところのプライマリキーを
 指しているのですか?もしそうであり、なおかつプライマリキーが人工キーである、
 たとえば hoge_id のようにデータ型が自動インクリメントされる整数(つまり)であるなら、
 自動的に一意性は保証されるから複合キーは考えなくていいでしょう。
 自分は(なるべく)人工キーは作らず複合キーで実装する立場ですが、それはまた別の話です。
402386:2011/02/27(日) 02:16:30.65 ID:???
>>397
値引きオプションだって修正や削除の必要が発生する可能性はあるから、
当然主キーつけるに決まってるよ。
そもそも実務的には値引き伝票切るケースが多いけどな。

その例えはお前の主張したいことからして全く適切じゃない。
もっとちゃんとした例を出せ。

> プライマリキーを設定するのかな。もちろんそれでも(AP開発に苦労はしても)要求仕様を
> 満たせるだろうから、どっちでもいいし、どうでもいいんだけどね。

お前、いつの時代の人間なの?
最近のアプリケーションフレームワークなら、むしろプライマリキーをつけないほうが
特殊な処理過ぎて苦労するだろうが。
403NAME IS NULL:2011/02/27(日) 03:53:37.69 ID:???
軽い実例を出してくれたほうが伝わりやすいことは業務をやってればわかることだと思うんだけど、
いつまで文字でがんばるのか。
404NAME IS NULL:2011/02/27(日) 07:35:09.08 ID:???
>>401

(1)確かに、1:0..Nと書いていたな。それを前提としているならばここはその通り。
(2)この文章は存在性を述べているわけではなく、存在性を条件に一意性の要否を
述べているんだろ?その上で、前提が(1)の通りであるならばBは常にAなしに存在
し得ないわけで、その条件は意味がないことになる。つまり「(2)Bにはプライマリー
キーは不要」とだけ書いても同じこと。
(3)やっぱり具体例がないと伝わらないか。
例えばテーブルBが{X,Y,Z}だとして、XがAへの外部キーだとしよう。
ここで候補キーが{X,Y}の場合、それをそのまま主キーとすることができる。
また、候補キーが{Y,Z}だとした場合であっても、主キーをXとの複合キー{X,Y,Z}と
する必要はない。
つまり、「外部キーと候補キーの複合キー」はいずれの場合でも必要ない。
候補キーの定義からして自明のはずなんだが。
405NAME IS NULL:2011/02/27(日) 10:13:02.26 ID:???
うざいから、ER図付きでやってくれ
406NAME IS NULL:2011/02/27(日) 10:17:07.66 ID:???
もともとの話は>>346に対する>>364の反論から始まってるんでしょ?

例えばブログの記事にタグ付けするような場合、
記事テーブル(記事IDがPRIMARY KEY)と
タグテーブル(記事IDがFOREIGN KEY)を作るとして、
364氏はタグテーブルでは何をPRIMARY KEYにするんだろう?

「子の主キーも設定する。親への外部キーはNOT NULLで参照する。」
と言っているからサロゲートキーを作るって話なんだろうな。

それだけの話だった(ように見える)のに、
以降の議論はただ話を難しくしてるだけのような。
407NAME IS NULL:2011/02/27(日) 11:23:29.66 ID:???
なぜサロゲート?タグテーブルには候補キーが存在しない前提なの?
408406:2011/02/27(日) 11:37:17.75 ID:???
どういう候補キーがあると思う?

記事IDとタグの組み合わせを主キーにするってのは考えられるけど
それだと「親への外部キーはNOT NULLで参照する」っていうのを
わざわざ書く必要がない。(主キーなら必ずNOT NULLだから。)

わざわざ書いてるってことは364氏の言ってる主キーには
外部キーを含んでないっていう前提があるんでしょ?
(あくまで推測ね。俺は364氏じゃないから。)
409NAME IS NULL:2011/02/27(日) 13:07:55.88 ID:???
>>364の真意は知らんが、「主キーに外部キーを含めない」と限定していたようには
俺には読めなかったな。含んでいようがいまいがNOT NULLということだろ?

1. わざわざNOT NULLと書いたから主キーには含まないんだろう
2. だとすると候補キーもないんだろう
3. じゃあ何をPRIMARY KEYにするんだろう?
4. たぶんサロゲートキーを作るんだな

3.の疑問を持った時点で自分の推測を疑えよって話だな。
410406:2011/02/27(日) 13:22:03.68 ID:???
うん、まあ、そうかもしれんしそうじゃないかもしれん。
どっちにしろ、364氏の真意が分からんことには議論はできないよね。
411NAME IS NULL:2011/02/28(月) 15:56:49.49 ID:???
364だけど、

>>406
「タグテーブル」が記事に対するタグ付けを表す(記事ID, タグID)、かつ
タグの順序に意味はないとして、同じタグを同じ記事に複数回付けられ
ないのであれば(普通の仕様だと思う)主キーは(記事ID, タグID)。
「[これはすごい][これはすごい][これはすごい]...」みたいに、同じ記事
に同一タグを複数回認める酔狂な仕様なのであればサロゲートキーも
必要。

後者は純粋に関係モデル的にはそもそもこのようなキーがないとデータ
を表現出来ない(setだから)。SQL的にはsetではなくbagだから無くても
表現できるけど、大抵は無いと更新時に填る。

>「子の主キーも設定する。親への外部キーはNOT NULLで参照する。」
>と言っているからサロゲートキーを作るって話なんだろうな。

いや全然。そんな話じゃない。
外部キー参照は仮に主キーを参照していてもNULLは入れられる。
「子単体は存在しない」、すなわち必ず親を持つのであれば明示的に
NOT NULLは宣言する必要がある。

>>409
>含んでいようがいまいがNOT NULLということだろ?

正解。
412NAME IS NULL:2011/02/28(月) 16:15:31.13 ID:???
もひとつ、>>346に聞きたいのは、>>346のルールとか、そのあと
改正した>>396のルールとか、これ教科書か何かに書かれたものなの?
であれば参考までにリファレンスを示してくれると嬉しい。
413406:2011/02/28(月) 18:47:49.98 ID:???
つまり、>>364
「子の主キーも設定する。親への外部キーはNOT NULLで参照する。」
は以下の意味だってことだろうから、俺は特に異論はない。

「子の主キーも設定する。
 ただし、要件によってはサロゲートキーとすることもあり得る。
 親への外部キーはNOT NULLで参照する。
 ただし、子の主キーが親への外部キーを含む複合キーである場合は、
 明示的にNOT NULLを指定する必要はない。」

346氏(=378氏?)は、単にサロゲートキー否定派なんじゃない?
414NAME IS NULL:2011/02/28(月) 19:49:10.77 ID:???
>>413
そゆこと。ただし以下の下りはちょびっと。

>ただし、子の主キーが親への外部キーを含む複合キーである場合は、
>明示的にNOT NULLを指定する必要はない。

必要ないし意味的にはダブるかもしれないけど、それでも明示的に
指定するかな。ごくごく個人的には、単に作法として。
テーブル定義を読んでも、parent_id *** NOT NULLと直接書いて
あった方がparent_idの取り得る値の制限としては解りやすいし。

>346氏(=378氏?)は、単にサロゲートキー否定派なんじゃない?
よくわからんす。自然キーでも人工キーでも、必要な場面で正しく
使えばどっちでもよいです。
415NAME IS NULL:2011/03/01(火) 00:15:51.62 ID:???
「弱実体」でググると>>346が言いたかったことと、どこが間違っていたかがわかるかも。
416NAME IS NULL:2011/03/01(火) 01:34:29.60 ID:???
>>396
> (2) もし存在しえないのなら、テーブルBは(エンティティではなく)属性を
>  表現することになるから、テーブルBへのプライマリキーの設定は不要

逆にエンティティA無しにエンティティBが存在しうるとすればどう
するの? プライマリーキー定義するの? どう決めるの?

> (3) 候補キー(たとえば作者カラム)
それは部分キーだ。候補キーじゃない。他のレスでも間違っている。
言葉遣いの問題だが、関係モデルの超基本だ。

> (3) その複合キーに対してUNIQUE制約を設定する。
なんでUNIQUE制約? PRIMARY KEY制約だとダメなのか? だってその
「複合キー」はテーブルB中の行を一意に選択出来るんでしょ? 主キー
の資格十分じゃん。
素のUNIQUE制約はNULL許可するけど、それでも良いの?
417NAME IS NULL:2011/03/01(火) 01:43:38.21 ID:???
>>397

> 具体的な例を挙げれば、値引きオプション、つまり「論理値の集合」で値を
> 表現するケースになる。ある行が商品を表現するとして、その商品に対する
> 様々な値引き(優待顧客値引き/個別値引き...etc)を 0個以上の任意の組合せで
> 表現することになるだろう。

関係従属性(商品, 値引きオプション) -> 適用可能[true or false]が存在。
なので値引きテーブルは(商品ID, 値引きオプションID, 適用可能)。
主キーは(商品ID, 値引きオプションID), 商品ID・値引きオプションIDに
外部キー制約。ちなみにBCNF。完璧じゃん。

主キーつけるのに何を悩む必要があるのか、それが解らない。
418NAME IS NULL:2011/03/01(火) 02:10:41.89 ID:???
>>378氏は一生懸命頑張って主キーがいるいらないの説明しているけど、
まず純粋にスキーマ設計の立場からいうと各テーブルの候補キーを特定
しておくことはマストだよね。でないと正規化が出来ん。

次に正規化が完了した関係スキーマをSQLで実装するときには候補キーに
対応する属性やその組に適切な制約をつけておくことは作法だよね。
でないとデータの整合性をアプリケーションレベルで保証する必要がある。

次に、それでも更新時のパフォーマンスの問題などで制約を外したい事は
無いわけじゃないよね。でも基本的にキーに対する制約を外すとテーブル
中の各行をアトミックに更新出来ることをDB側で保証できなくなる。
なのでその部分はアプリ側で制約するとか、更新の対象や単位を詳細に
見極めて判断したりする必要がある。

ましてや>>344は初心者だといっているのだから、教科書通りER図など
から主キーも含めたテーブル定義を導出する方法で良いじゃないか。
419NAME IS NULL:2011/03/01(火) 03:10:14.37 ID:???
みんな教科書通りにやろうとしてるぜ
みてる教科書の分野が微妙に違うんだがな
420NAME IS NULL:2011/03/01(火) 04:11:06.16 ID:???
>>417
関係従属性 -> 関数従属性。
関係モデルの超基本だ・・・釣ってくる・・・
421デフォルトの名無しさん:2011/03/04(金) 00:09:48.83 ID:nwTUgCQG
話をサロゲートキーの話題に戻すが、

@商品マスタの商品コードが変わったときの話だが、
 サロゲートキーにしておけば、コードの付け替えが楽。

Aトランザクションにてその時点のマスタ値を保障する方が安全
つまりトランザクションには、商品ID、商品コード、商品名等を
すべて保持する。

@とAは明らかに同時に成り立たないわけだが、
この矛盾はみんなどうしてる?

あと、階層関係があるマスタ、たとえば事業部マスタと部門マスタで
事業部と部門の紐付けが変更されうる。部門の名称変更がある等の理由で、
適用期間をおのおの持った場合、サロゲートキー(事業部ID)
だけでリレーションさせると、事業部マスタの世代が増えたタイミングで、
リレーションが破綻するわけだが、どうしたらいいんだろ。
422NAME IS NULL:2011/03/04(金) 00:38:25.10 ID:???
> @とAは明らかに同時に成り立たないわけだが、
> この矛盾はみんなどうしてる?

矛盾なんかしてません。
馬鹿じゃないの?

> 適用期間をおのおの持った場合、サロゲートキー(事業部ID)
> だけでリレーションさせると、事業部マスタの世代が増えたタイミングで、
> リレーションが破綻するわけだが、どうしたらいいんだろ。

どういうシチュエーションでどういう設計をしたら破綻するのか
全然イメージがわきません。
多分サロゲートキーじゃなくてお前の頭が悪いんだと思うよ。
423NAME IS NULL:2011/03/04(金) 00:55:03.15 ID:???
>>421
サロゲートキーの使い回しをせず、商品コードの書き換えもマスタ
への追記で対応すれば(2)は本来不要なんじゃないのかな。
424NAME IS NULL:2011/03/04(金) 01:36:28.45 ID:???
まず、この例で言うなら、商品コードが変わった場合
過去に登録されたトランザクションデータをどうしたいかを考えろよ

過去データを塗り変えたいなら1が便利
過去データはそのまま保持したいなら2が便利

それだけの話だろ
違う要件に対する解決案をならべて同時に成り立たないって当然だろ
425NAME IS NULL:2011/03/04(金) 01:39:40.34 ID:???
履歴とリアルタイムデータの区別が付いてないっぽいな
426NAME IS NULL:2011/03/04(金) 01:57:35.75 ID:???
>>424
2にしてもトランザクションデータに追記する際に商品コードとか
商品名などを商品マスタの内容からコピペしているのであれば結局
1で対応出来るのだが。

商品マスタは基本追記で、最新フラグとか削除フラグとか付けて
古い商品レコードも全て保持するのは案外一般的だと思うけど。
427NAME IS NULL:2011/03/04(金) 20:05:10.85 ID:???
サロゲートキーでよくわからないところがあるんだが
本来pkになるはずだった項目の制約はどうすんの?
前に張られたこのURLの例では、制約について一切触れてないから、そんな制約張りませんってことなのか・・・?
http://gihyo.jp/dev/serial/01/sql_academy2/000304
428NAME IS NULL:2011/03/04(金) 20:14:23.32 ID:???
制約つければよくね。
429NAME IS NULL:2011/03/04(金) 20:25:51.61 ID:???
NOT NULLとUNIQUEでいいじゃん
430NAME IS NULL:2011/03/04(金) 20:28:03.50 ID:???
>>428
もともとpkにする予定だった項目には、例外なくuniqueを張りたいんだけど
>>427の例ならどうするべきですか?
431NAME IS NULL:2011/03/04(金) 20:35:13.01 ID:???
>>427
場合によるとしか言いようがない。
挙げられた例だともともと主キーだったitem_noにUNIQUE制約とか
は付けられないよね。同じitem_noを使い回すので。

沢山の属性を組み合わせた複合キーをシンプルなサロゲートキーで
置き換えるような場合は、主キーこそサロゲートキーにしたとはいえ
元々の複合キーも未だに候補キー、つまりキーに含まれる属性値の
組み合わせはユニークなはずなので、UNIQUE制約を付けた方が良い。
432NAME IS NULL:2011/03/04(金) 20:36:53.99 ID:???
>>430
item_no(商品ID)とitem_name(商品名)の組み合わせに対して
UNIQUEだろうね
しかし>>427の例って商品ID自体が自然キーじゃないよな
433NAME IS NULL:2011/03/04(金) 20:55:19.98 ID:???
>>427のように、同じitem_noを使い回すのであればテーブルには更に
最新フラグとか削除フラグをつけることが多いと思う。
[id(サロゲートキー), item_no, item_name, deleted]みたいな感じで。

で、上記の例の場合は削除フラグdeletedがfalse、つまり現在有効な
行の中でitem_noのダブりがあると困るわけなのだけど、この制約を
書くのはちょっと面倒くさい。フラグ値を工夫するとか一般制約を
使うとかすれば書けるけど。
実際はアプリケーションレベルでタブりを事前確認するロジックを
書くことが多いんじゃないのかな。
434NAME IS NULL:2011/03/04(金) 21:06:10.73 ID:???
>>431
>つまりキーに含まれる属性値の組み合わせはユニークなはずなので、UNIQUE制約を付けた方が良い。
この部分がよくわからないんですが、もうちょっとスキルが低い人にもわかるようにお願いできませんか?

>>432
名称もunique制約に含めるって、普通に行われることですか?
見たことが無いのでちょっと抵抗があるんですが。
それから、>>427の例の商品NOは、人口キーのようなどうでもいい文字列ってわけじゃなく
お客さんのなんらかの都合により使いまわされる事がある、お客さんも把握してる文字列なわけですから
自然キーの典型的な例だと思うんですが、違うんでしょうか?

>>433
変なデータができあがっちゃうとまずいんで
私が見たことのあるDBでは2重に重複チェックしてました。
具体的には、プログラム側でマスタを更新するまえにDBに問い合わせてチェック→重複してるようならweb画面にエラーを出す
プログラム側のチェックを通ったあとも、unique制約により、DB側でチェックが行われ、これも通れば更新されるといった仕組みでした。

おそらく削除フラグを付けたほうがいいというのは、期間でなくフラグを参照することで
select文を発行するときの負荷が減るというのが目的ですよね?
重複チェックはなかなかミスが出るようなところじゃないから、アプリ側できっちりやれってことでしょうか?
435NAME IS NULL:2011/03/04(金) 21:30:12.87 ID:???
>>434
プライマリキーのカラム数が5個ぐらいあって、Joinがしんどくてしんどくてしょうがないという理由から
ただの連番のカラムを作って、それをキーとするようにしてみた
という状態であれば、もともとの5カラムにユニーク制約つけたままで問題ないよ
436NAME IS NULL:2011/03/04(金) 21:32:21.28 ID:???
>>432
それがUNIQUEになるなんてただの思いこみなんじゃないかって思う
437NAME IS NULL:2011/03/04(金) 21:35:44.50 ID:???
>>435
すごくわかりやすい、ありがとう。
効果は開発効率のアップと、select文のコストが少し減るって感じかな?

その目的でサロゲートキーを使う場合
全てのテーブルにサロゲートキーを追加するんじゃなくて
pkの項目が多くなりそうなテーブルにだけ追加するのが良さそうですね。
サロゲートキーを使用するテーブルの場合、例外なく最初の列に「PK_テーブル名」というカラムを作り
それをサロゲートキーにするというルールで設計すれば、アプリチームの混乱も防げて良さそうですね。
438NAME IS NULL:2011/03/04(金) 21:41:20.76 ID:???
>>434
例えば月給テーブル(社員ID, 年, 月, 給料)を考えてみる。
主キーは(社員ID, 年, 月)ね。

で、理由はともあれ誰かさんが属性3つの複合キーなんて非効率的だ!
サロゲートキーにしろ! と叫んだとする。で、サロゲートキーSIDを追加して
月給テーブル(SID, 社員ID, 年, 月, 給料)、主キーSIDにしましたと。

で、このテーブルをよく見てみると、確かにSIDはキーですが、元々の主キー
(社員ID, 年, 月)もテーブル内の行を一意に特定出来るキーなんですね。
というか一意に特定出来ないと困る。でないと同じ社員が同じ年・月に複数回
給料もらえちゃいます。

関係モデルでは一つのテーブルが複数の「候補キー」を持つことがあります。
この場合はSIDと(社員ID, 年, 月)の二つの候補キーがあります。
その中から「主キー」を一つだけ選ぶわけですが、だからといって残った他の
候補キーがキーでなくなるわけではありません。それらも引き続いてキーです。
なので上記の例だと候補キー(社員ID, 年, 月)にUNIQUE制約を付けておく
必要があります。
439NAME IS NULL:2011/03/04(金) 22:00:25.24 ID:???
>>434
>おそらく削除フラグを付けたほうがいいというのは、期間でなく
>フラグを参照することでselect文を発行するときの負荷が減ると
>いうのが目的ですよね?

例えばサロゲートキーを使った商品マスタテーブルを使って実際に
トランザクションデータを書き込むとき、伝票に書かれた商品IDから
サロゲートキーを逆引きする必要があります。
しかし>>427のテーブルの場合、商品ID001からサロゲートキーを
逆引きすると二つサロゲートキーの値が出てきます。これはで困る。
なのでフラグを付けて現在も有効なレコードだけから検索するように
する必要があります。
もちろん特別にフラグを設けずに、例えば有効期間を表す列に「現在も
有効」を表す特別な値(>>427の例だと"9999")が仕様として定義されて
いる場合はこれを使って絞り込んでもよいわけです。

ただこの手の終了フラグを使った場合、商品IDのタブりを防ぐ制約は
やや凝った記述になりがちで、となると現状PRIMARY KEYなど基本
どころ除けばDBMS毎に書ける制約の表現力がバラバラなのが難しい。
MySQLなんてCheck制約は書けてもガン無視するとか、そんな仕様。
なんでアプリ側でチェックするロジックを書くことも多い気がします。
440NAME IS NULL:2011/03/04(金) 22:26:37.03 ID:???
>>438
丁寧な説明ありがとう。
この板はIDが無いみたいなんで、どのレスをした人がどのレスを返してくれてるのかわからないけど
>>435>>438は同じ事ですよね?


>>439
MySQLでcheck制約がきかないのは初めて知りました・・・なんと恐ろしい。
>>427の場合は、トランザクションテーブルに書き込む商品の情報は
商品IDじゃなくてsrg_key(サロゲートキー)じゃないですか?

>>427の例の仕様ではこうなってるはず
・マスタのpkはサロゲートキーを使用する。
・トランザクションテーブルの外部参照をする列に格納するキーは、参照先のサロゲートキーを入れる。
・過去に入力された名称は、その時点で入力された名称をマスタから取得する。
・unique制約は付けない。


サロゲートキーの一つの利点である、pkに指定する項目が1つになるという部分は理解できました。
どこのページを見てもあんまり紹介されてませんが
unique制約が付けづらいというのはサロゲートキーのデメリットとして覚えておいた方が良さそうですね。
441デフォルトの名無しさん:2011/03/04(金) 22:32:56.51 ID:???
商品IDがダブらないなら本質的にサロゲートキーは不要かと…
やばいのは商品IDというか商品コードがメーカーによって使いまわされて、
ある製造日より別商品に割り当てられたが、
販売店の在庫管理としては商品コードと入荷日でしか
管理していなかったため、同一商品コードの違う製品が混在してしまって
何を販売したのか管理できず混乱するなどですよね。
442NAME IS NULL:2011/03/04(金) 22:45:47.53 ID:???
>>441
得意先のマスタなんかは在庫とかって概念がないからどうゆうふうに設計してもなんとかなりそうなもんだけど
商品に関しては商品IDを使いまわす可能性があるならサロゲートキーは必須になるのか
443NAME IS NULL:2011/03/04(金) 22:50:32.51 ID:???
すごーーーーく根本的な話になるんだけど
商品IDの使い回しを行いたい時ってどうゆう時?

得意先や部署はわかる。
合併やら統合やらあるもんね。
商品IDはわからん。
444デフォルトの名無しさん:2011/03/04(金) 23:00:00.52 ID:???
桁数だろう?
どれだけ必要になるかわからないからって
たとえば20桁のコード体系をあらかじめ用意するのかってこと。
覚えられん…
445NAME IS NULL:2011/03/04(金) 23:10:09.40 ID:???
>>443
古いシステムならコードのMAXが5桁とか普通に有り得るだろう。
446NAME IS NULL:2011/03/04(金) 23:18:26.31 ID:???
えー・・・
447NAME IS NULL:2011/03/05(土) 00:12:24.71 ID:???
くるくる回る商品IDなんてよくある。
ある時点においてユニークであれば、それで現場は回っていくんだよ。
なもんで、こっちとしてはサロゲートキーを作って、商品IDガン無視する。

たとえ今はいらなくとも、商品IDで検索したいってなったときに困らないように、
ある時点で有効な商品IDがどれかを特定できる情報を保持しておく。
448NAME IS NULL:2011/03/05(土) 00:39:28.99 ID:???
俺の場合、
自社に決定権がないコード体系のマスタ(商品など)は、サロゲートキー
自社に決定権があるコード体系のマスタ(得意先マスタ)はナチュラルキー
ジャーナルのヘッダはサロゲートキー、
ジャーナルの明細はヘッダのID+明細番号の複合主キー
とすることが多いが、これって古臭い?
449NAME IS NULL:2011/03/05(土) 01:22:17.28 ID:???
雑誌コードなんか桁が足りなくて新規発番が出来なくなって使い回してるよな

450NAME IS NULL:2011/03/05(土) 01:28:21.09 ID:???
そうゆうことか。
周辺システムが古くて桁数が少ないので
商品IDを使いまわさずを得ないと。

>>441みたいな場合ってどうなるの?
頻繁に商品IDが付け替えられて、古いほうの在庫も残る可能性がある。
同じ商品IDで、商品そのものも名称もまったく違う商品が存在する。

Web画面で商品を入力するためのボタンがあって、ポップアップで検索ボックスみたいのが出てきて
IDで検索すると同じ商品が複数出てくる。
それを選択してもらう。

Webの入力画面でコードを手打ち入力した場合の動作は?
ajaxとかで名称ひっぱりたいとこだけど、複数出てきた場合は新しい方を出したりするのかな?

なんにせよ恐ろしい・・・
こうゆう運用ならサロゲートキーは必須だ・・・
451NAME IS NULL:2011/03/05(土) 02:15:11.10 ID:???
>>448
その得意先マスタのキーって得意先IDみたいなの、つまりサロゲーとキーでは?
ナチュラルキーになりうるのってなんだろうとぐぐってみたところ、
上場企業限定ならISINコードというものがあるようだけど、これなのかなぁ

>>449
休刊して番号温存だね。あるある。

>>450
客から見て、在庫も含めると異なる商品に対して同じ商品IDがついているけれども、
業務を滞りなく行えているのであれば、何も悩む必要はないよね。
こちらとしてはサロゲートキーで処理をしてしまえばいいだけだよー
452NAME IS NULL:2011/03/05(土) 02:17:08.29 ID:???
>>450
加えて、商品IDでの検索結果が複数出てきたなら複数出せばいいんだよ。
それで業務がまわっているということが不思議だなぁと思うことはあれど、
それを正としなければいけないしねw
453NAME IS NULL:2011/03/05(土) 02:30:08.03 ID:???
>>451
>上場企業限定ならISINコードというものがあるようだけど、これなのかなぁ

>>448の言う「自社に決定権があるコード体系」というのは、
そういった業界標準コード体系を意味しているのではなく、
業務の中で自然に発生する自社特有のコードを指していると思う。

たとえば、紙の受注伝票に記入する得意先コードや受注商品コードというのは、
自社特有の(自社で決定できる)自然キーである可能性が高い。
逆に、発注伝票に記入する発注商品コードというのは、
(自社では決定できないから)人工キーとせざるを得ない可能性が高い。
454NAME IS NULL:2011/03/05(土) 16:14:51.45 ID:???
お前ら、商品ID商品ID言ってるけど、使いまわした時点でIDとしての役割を果たしてないだろうが
商品コードを使いまわす、が正しい用語だ
455NAME IS NULL:2011/03/05(土) 17:59:31.77 ID:???
まぁ目安だよな。あくまでも、自分が定義したエンティティに対してそのコードが
一意であるがどうかで判断すべきであって。
・よそで定義されたコード→一意でない「可能性がある」
・自分で定義するコード→当然一意に「できる」

極端な話、実際の商品の品種と商品コードの一意性が一致しない場合であっても、
「商品」ではなく「商品コード」エンティティを作る分には商品コードをそのままキーと
してもぜんぜんかまわないわけだ。
456NAME IS NULL:2011/03/07(月) 20:06:48.91 ID:???
>>453
>自社特有の(自社で決定できる)自然キーである可能性が高い。
純粋な意味では、自然キーではないよね。w
457NAME IS NULL:2011/03/07(月) 20:11:28.00 ID:OIEGkLgo
>>440
>MySQLでcheck制約がきかないのは初めて知りました・・・なんと恐ろしい。
こわくないよ?

つーか、それっておいしいの?
MySQLしか使わないオレには、よく
わからん話なんだよな。
458NAME IS NULL:2011/03/07(月) 20:53:11.82 ID:???
>>456
システムの外で定義されるのが自然キーだろ?コードが人工的かどうかじゃなくて。
そんなこといったら、人名とか市町村名なんてどっちか判断つかん。
459NAME IS NULL:2011/03/08(火) 05:36:45.40 ID:???
>>457
知らない者にとっちゃ恐ろしいだろ。
定義できるのにまさか動かないとは思わないだろうし。
460NAME IS NULL:2011/03/09(水) 01:13:08.54 ID:???
>>454
このスレでのID、コードの使い分けって一般的に通用するものなの?
いや、自分もそういうふうに使い分けてるんだけど、他の人がそんな風に気にしてるの見たことがないので。
461NAME IS NULL:2011/03/09(水) 01:47:19.22 ID:???
>>460
基本的には普遍でユニークな社員番号(商品ID)と、変更可能な姓名(商品コード)、
みたいな形で一般人も接してはいる。
462NAME IS NULL:2011/03/09(水) 15:48:40.12 ID:???
>>460
まあ、大概の人は混同してる。このスレでも混同してる人もいるしな
一般の人にとって、コード振ってあるのに別にIDとるのは無駄に思えるんじゃね
463NAME IS NULL:2011/03/09(水) 20:21:29.21 ID:???
「混同」っていうと、まるで使い分けないのがおかしいみたいだな。
2行目をみるとそれぞれ別物のなにかを指しているというのはわかるんだが…
464NAME IS NULL:2011/03/10(木) 06:07:06.59 ID:???
IDでもコードでも俺はどっちでもいいな。
使い分けてないプロジェクトがあっても、sql書く時に項目名間違えづらいなぁ程度にしか思わない。
465NAME IS NULL:2011/03/10(木) 09:17:01.62 ID:???
>>458
システムの外で「独立して」定義されるのが
自然キーだろ?
顧客コードなんかデータベース以外に
ほとんど用途がないんだから。
466NAME IS NULL:2011/03/10(木) 15:38:23.73 ID:???
>>463
ID=コードなシステムもまあよくある
というか、IDとコード別にもつシステムの方が少ないと思うけど

IDとコードもつシステムの例はコード使いまわされるようなやつとか
「その他」とか「一般小口」とかのコードもってるシステムとか

IDっていう用語の意味を考えると、厳密に区別できないとIDじゃないからな
467NAME IS NULL:2011/03/10(木) 22:58:24.84 ID:???
>>465
この場合の「独立して」ってどういうことを意味しているのかな?
ここで挙げられた顧客コードってのは、「システムの外で定義されるけれども独立してない」例?
468NAME IS NULL:2011/03/11(金) 04:29:35.90 ID:???
独立していない可能性がある、または随時変更される可能性があるコードなんじゃない?
客から見えるコードだと、コードを振りなおしたい要求って結構くるよね
469NAME IS NULL:2011/03/11(金) 07:32:25.94 ID:???
>>465
>顧客コードなんかデータベース以外に
>ほとんど用途がないんだから。

ええぇっ!!、それが常識なの?
自分のいる世界とは別の異次元な世界の住人さんらしい.... hahaha
470NAME IS NULL:2011/03/11(金) 11:13:05.74 ID:???
「データベース」の意味をどう捉えてるかによるだろうな
471NAME IS NULL:2011/03/11(金) 11:34:03.00 ID:???
「データベース」でくくるとさすがにちょっと狭いと思うぞ
ほとんど「情報処理」とか「システム化」と同じぐらいまで解釈を広げればまあ納得しなくはないが
472NAME IS NULL:2011/03/11(金) 13:15:03.35 ID:???
台帳をデータベースと呼ぶかどうか
473NAME IS NULL:2011/03/11(金) 13:18:57.55 ID:???
>>469
そんな反応しなくてもw
そこだと、顧客コードは恒久的に変わらないことが前提で、顧客コードで会話等がされてるんでしょ。
その業務であればそのコードはIDであり、自然キーといっていいと思うよ。
474NAME IS NULL:2011/03/13(日) 03:34:25.71 ID:???
どのスレが適当か探してみたんですが、スレ立てるまでもない質問スレが見つからなかったので、ここで質問させて下さい。
病院で働いているんですが、今、上司からの依頼で、内視鏡検査の画像をデータベース化する作業をしています。
現在のシステムに以降する前の約2年分、件数にして4000件ぐらいのデータです。
データ形式ですが、約3ヶ月分ずつのデータがDVDにまとまっていて、DVDの中に入っている.exeファイルを起動して閲覧する、というものを、何とか一つのデータベースにまとめたいと悩んでいます。

各データは一件あたり数十枚で、たとえば34枚だとすると、フォルダ名00001、その中にjpeg画像00001から00034が34枚格納されていて、つぎの件はフォルダ名00035となり、その中にまた画像一枚ずつに数字でファイル名がふってある形でした。
閲覧ソフトに患者名かIDか検査日を入力すると、画像が閲覧できます。
DVDに入っているのは画像フォルダ、恐らく画像とひも付けしたログファイルのフォルダ、あと閲覧ソフトです。

こういったデータを、Windows上で現在のシステムに移植するには、(オリンパスの出入り業者に確認した話ですが)一件一件検査オーダーを立てて、画像を指定する必要があるとのことでした。
自動でデータを読み出して全ての過去データDVDをデータベース化するか、現在のシステムに移植するには、どういうソフトを使えば可能でしょうか?
軽く調べたところ、SQLとやらいうスクリプトの話がでてきましたが、ド素人なので厳しいかと正直諦めかけてますorz
よろしくお願いします。
475NAME IS NULL:2011/03/13(日) 03:48:10.98 ID:???
>>474
多分この内容だと情報が足りなすぎて誰もアドバイス出来ないと思う。
ファイルの格納の仕方は「なんだそれ」という感じではあるけれども
サルベージ出来ないわけでもない。多分ネックは、

>恐らく画像とひも付けしたログファイルのフォルダ

の中身と

>Windows上で現在のシステムに移植するには

の「現在のシステム」が分からないと、どうにもならないかと。
ただ間違ってもログファイルの抜粋をこのスレに貼り付けたりは
しないでね。

いずれにしても出来合いのソフトで出来そうな作業じゃない。
専用のマイグレーションのためのプログラムを書く必要はある。
476NAME IS NULL:2011/03/13(日) 04:30:03.11 ID:???
>>475
レスありがとうございます。
やはり専用のプログラムが必要ですよね…
現在のシステムは、内視鏡サーバーに全て検査内容が直接スタックされるもので、オリンパスのsolemio というものです。
検査一件一件のデータをログから指定して、画面上の場所指定でオートクリック、ログ入力、画像指定が出来るソフトというと、オンラインゲームのチートソフトくらいしか思い付かず、それにしたってログを読み出すプログラムが別に必要になりそうな予感はしていました。

ちなみにログの抜粋がアウトなのは個人情報の関係ですか?
477NAME IS NULL:2011/03/13(日) 04:37:50.27 ID:???
>>476
医療情報流出〜匿名掲示板でアドバイスを装って診察データを入手か〜

・・・なんてニュースになりたくないでしょw

オリンパスにデータインポーター提供してもらうしかないんじゃない
のかなぁ
478NAME IS NULL:2011/03/13(日) 05:08:53.69 ID:???
>>474
画像の格納方法に規則性があるなら、画像を取り出すことは出来るかもしらんが、
「患者名かIDか検査日を入力すると〜」がネック。おそらくこの他にも情報があるんだろうけど、これらのサルベージ方法が問題。
フォルダの中にテキストで埋めこまれてるとか言う間抜けな作りなら個人PGでも解析出来るだろうけど、さすがにそんなことはないだろうな・・。
そもそも元システムのライセンス的にどうかとかなりかねないし。

逆に解析を諦めるなら、最終手段で人がPC2台使って手入力でやれば出来る(つまり出入り業者の言う、「一件一件検査オーダーを立てて、画像を指定する」)。
この最終手段の可能性コミで、オリンパスに見積もってもらうのがベストだと思う。ただ人海戦術は安くないけどね。
479NAME IS NULL:2011/03/13(日) 06:48:05.90 ID:???
>>474
ざっと読んでみて、まず基本的な課題を挙げてみる。

(1) ストレージ管理
 4000件のデータで各データが数十枚のDVDに格納されているというデータ量が膨大なケースだけど、
 それらコンテンツのカタログ(目録)だけをデータベースすればいいのか(= カタログDB化)?あるいは
 すべてのコンテンツをストレージ(要はハードディスク)内に格納するのか(= 画像DB化)?という判断。
 もし前者であればソフトウェア(アプリケーション開発)だけ対応できるけど、
 後者の要求を叶えるとすれば専用のストレージハードウェア導入も検討対象になる。

(2) 遺産データのデータ形式仕様
 DVDに格納されている過去データについて、そのデータ形式仕様を把握する必要性があるという課題。
 データ形式仕様には、(a) DVDボリューム構成、(b) DVD内のディレクトリ/ファイル構成、
 (c) ログファイルのデータ構造などがある。この課題を、より具体的な副課題に分解してみる。

 (2-1) その遺産データの作成者から仕様書を入手
  作成した外部の業者(あるいは院内の担当者?)に問い合わせて入手できるのが理想。
  もし入手不可であれば、自力で分析する、いわゆるリバースエンジニアリングという作業が必要。

 (2-2) 入手した仕様書と(DVDに格納された)実データに一貫性があるかを検証
  理想的には、すべての実データが仕様書に従って作成されていれば、
  (相対的に)単純なスクリプト(プログラミング)でデータ移行処理が可能になる。
  最悪なのは、手作業でDVDボリューム名/ディレクトリ名などを決めて焼いていたケース。

 (2-3) ログファイルのデータ構造について機械可読性を確認
  理想的なのは、XMLのような形式的なテキスト形式で保存されている場合。
  もしも独自のバイナリ形式であれば、(2-1)のデータ形式仕様書の入手が必須になる。
  最悪なのはフリーなテキスト形式のケースで、一件ずつ手作業で編集しなければならなくなる。

(3) 新規アプリケーション開発の必要性
  理想的には、(2)の作業を経て準正規化(機械処理可能化)された中間データを、現行の(OLYMPUS?)
  システムへ移行する(相対的に単純な)変換プログラムを作成することで、課題が解決できるケース。
  もしもそれが不可であると判断されたなら、その中間データを元に新規DBの開発を検討する。
  その場合には、どのようにDBを設計すべきか?という、このスレ住人向きの話題にようやく辿り着く。
480479:2011/03/13(日) 07:23:59.19 ID:???
>>479の課題(3)で新規DB開発を決定した場合に限定される話だけど、
医療関係者が(外部の業者に頼らずに)自力でデータベース化を図るとしたら、
FileMaker Pro というDBアプリケーションがよく知られている。
FileMaker Pro は、Microsoft製であればAccessに相当するデスクトップDBソフトだけど、
SQLを憶える必要は無いし、テーブル設計/画面デザインからスクリプト作成まで
すべてGUIで操作できるから、簡易なDBであれば専門家でなくても開発できるのでお勧め。
(個人的にはシステム分析初期段階のラピッドプロトタイピングに活用している。)

たとえば以下の医療画像管理アプリはソースも公開されている。

・マイコミジャーナル:ファイルメーカ選手権(第一回)月間優秀賞:患者画像記録
 http://journal.mycom.co.jp/ad/contest/filemakersenshuken/01.html#2

FileMaker Proは試用版が無償で利用できるから、まずダウンロードして触ってみるのがいい。
質問等はビジネスsoft板に専用のスレがあるから、そちらへドーゾ。
481NAME IS NULL:2011/03/13(日) 16:43:53.66 ID:UrDSEA55
「はてな」や楽天のポイント履歴を見ていて思ったのですが、
ああいう頻繁にレコードの追加が発生するコミュニティサイトって
1テーブルのフィールド構成をどうしているのでしょうか?
単純に「日付|ポイント数|対象ユーザID|対象動作ID」
で分けてるだけでしょうか?

でも、そう考えると、ユーザ数×履歴数で倍々に増えていくので
万単位の会員数があるサイトでは、ポイント履歴テーブルに
レコードが溜まりすぎるのではないか?と言う懸念があります。

ポイントというお金と変わらないものですから、
「○件まで保存。後は削除」と言うことはなかなか出来ないと思いますし・・・
482NAME IS NULL:2011/03/13(日) 17:03:45.55 ID:???
ヒント:それらのケースでは厳密なACIDは要求されない。
    (もちろん楽天の商品注文処理には厳密なACIDは要求される。)
483NAME IS NULL:2011/03/18(金) 16:34:48.59 ID:N3L942K+
ショッピングサイトでのDB設計について
・注文テーブル、
・会員テーブル
があります。
会員が注文した場合は会員IDを外部キーとして注文テーブルに入れればいいのですが、
会員じゃない人からも注文が入るので、
注文テーブルに会員テーブルと同じようなフィールド(名前、送り先住所など)を入れて、
注文レコードに、会員ID(外部キー)が無い(NULLの)場合は、同じ注文レコードの名前や住所を参照しようと思っています。

もう1つは、会員テーブルと同じような、非会員テーブルをつくり、
会員じゃない人の住所情報などはそこに入れようという方法です。

後者の方が個人的にきれいな設計だと思うのですが、
この場合注文テーブルに入れる外部キーをどうするかがまた問題になって困っています(外部キーが非会員IDなのか会員IDなのかわからなくなる)。

これを解決するために、
非会員注文テーブル、
会員注文テーブル
と2つに分けることも考えていますが、
ここまですると逆に注文テーブルが2つになってしまうのできれいじゃなくなる気がします。

どうするのが一番良いでしょうか
484NAME IS NULL:2011/03/18(金) 16:40:17.60 ID:???
無駄すぎ
注文テーブルと会員テーブルだけでいいですがな
485NAME IS NULL:2011/03/18(金) 17:21:13.97 ID:???
>>483
まず最初にモデル分析について。
前者は論外。注文テーブルでは注文に関する情報だけを定義すべき。
残る後者について、「会員の人」と「会員じゃない人」という概念は、
人に関する集合を意味するわけだけど、これら両方を包含した全体集合を考えなさい。
たとえば「取引先」という概念は一般に両者を包含するからよく用いられる。
あるいは全体集合を「会員」として位置付けて、部分集合を「正会員(会員の人)」と
「会員候補(会員じゃない人)」とに分割するという、逆の発想でもかまわない。

次に実装についてだけど、これもいくつかの方法がある。
たとえばモデル分析で全体集合を「取引先」とし部分集合を「会員」および「非会員」とした場合、
テーブルとしては「取引先テーブル」だけを定義し、そのフィールドとして会員区分コードを設ける方法。
あるいは各集合に対応する3個のテーブルを定義する方法もある。この場合、「会員テーブル」と
「非会員テーブル」には外部キーとして(取引先テーブルを参照する)取引先IDを設けることになる。

どちらの方法を選ぶにしても、注文テーブルの外部キーは取引先IDだけになるから、課題は解決される。
486NAME IS NULL:2011/03/18(金) 17:51:34.01 ID:???
>>483
会員が自分の住所以外を送り先として注文することはないのかな?
487NAME IS NULL:2011/03/18(金) 18:02:59.08 ID:???
>>485
前者は論外、とも言えないんじゃないのかなぁ。
会員IDがNULLの時だけ名前や住所の値を参照するという運用には
とても疑問があるけれども。

483は取引後に会員の名前が住所や変更される可能性と、その場合
も過去の個別の注文に関してはその当時の住所や名前を保存して
おく必要性(普通は必要だと思うけど)を考えるべきだと思う。

その場合には注文テーブルにも名前や住所などのカラムを作って
注文毎に会員情報から転記する方法と、少し前に散々議論された
会員情報をサロゲートキー使って管理する方法がある。
488NAME IS NULL:2011/03/18(金) 18:55:00.36 ID:vy9E5dGG
論理キー(複合キー)があるのに、わざわざID列を主キーに作るの勘弁してくれ。
489NAME IS NULL:2011/03/18(金) 20:32:06.47 ID:???
単にSingle Table Inheritanceの典型的なケースではないの?

この辺を参考にすれば
http://capsctrl.que.jp/kdmsnr/wiki/PofEAA/?SingleTableInheritance
490NAME IS NULL:2011/03/18(金) 21:45:08.46 ID:vy9E5dGG
典型的なプログラマー脳orパッケージ屋さんか?
491NAME IS NULL:2011/03/18(金) 22:02:10.77 ID:???
ではDB屋さん的な回答どうぞ。
492NAME IS NULL:2011/03/18(金) 22:16:11.36 ID:???
・注文テーブル
・顧客テーブル
・会員テーブル

に分ければ良いだけじゃん。
注文テーブルの顧客IDと顧客テーブルのIDをJOINして
顧客テーブルのIDと会員テーブルのIDをJOINする。

会員テーブルには、ID/パスワードなど、ログイン専用のデータだけを保存する。
こうすれば会員じゃない人は顧客テーブルの参照で済むし、
会員なら会員テーブルまで参照すれば良いだけのこと。
493NAME IS NULL:2011/03/18(金) 22:26:40.26 ID:???
・注文テーブル (送り先の名前・住所入り)
・会員テーブル (会員の名前・住所入り)

かな。送り先の名前や住所は会員IDではなく注文IDに関数従属
するものだから、別のテーブルに分ける理由がない。

もちろん会員テーブルを過去の更新分も含めてサロゲートキーで
管理して、非会員の情報についても別の顧客テーブルなんちゃら
に分ける方法もあるけれども、無駄にスキーマが複雑になる。

判断は会員/非会員の注文の割合とか(非会員の注文が例外的か)
とかにも依存するけれども、単に注文毎に送り先を保存したい
場合は上のやり方が一番シンプルで良いと思うんだけど。
494NAME IS NULL:2011/03/18(金) 22:29:31.66 ID:N3L942K+
>>484
会員テーブルに、非会員フラグなどのフィールドを入れるということですね?

>>487
> 483は取引後に会員の名前が住所や変更される可能性と、その場合
> も過去の個別の注文に関してはその当時の住所や名前を保存して
> おく必要性(普通は必要だと思うけど)を考えるべきだと思う。
それは全然考えてなかったですね・・・たしかに必要かも。

ということは、
>>492
の方法が一番良さそうですかね?
この>>492の顧客テーブルというのは、注文の住所や名前情報などがはいるんですよね?
注文レコードの数=顧客レコードという認識ですが正しいでしょうか
495NAME IS NULL:2011/03/18(金) 22:33:01.55 ID:N3L942K+
>>493
この方法も良さそうですね
496NAME IS NULL:2011/03/18(金) 22:42:31.73 ID:???
>>494
・注文テーブル → 注文日時、ステータス、商品合計金額
・(注文商品テーブル) → 注文した商品のIDと価格
・顧客テーブル → 名前や住所
・会員テーブル → ログインIDやパスワード

こう考えてみたらどうだろう
497NAME IS NULL:2011/03/18(金) 22:53:33.73 ID:???
>>490

めちゃくちゃDB設計の話だと思うけど
498NAME IS NULL:2011/03/18(金) 23:00:42.16 ID:N3L942K+
>>493の方法でいいかなと思っているのですが、
>>493の方法と比べて>>496の方法(顧客テーブルをはさむ)のメリットはなにがありますか?
499NAME IS NULL:2011/03/19(土) 00:18:10.77 ID:???
>>498
>>493の方法の場合、例えば会員から注文があった場合には会員テーブル
から会員の名前や住所を送り先として注文テーブルに転記する必要がある。
会員の名前や住所はそうそう変わらないだろうから、同じ情報がテーブル
中に繰り返し現れるわけで、そういう意味では冗長でストレージの無駄。
>>496の場合は、これがない。

ただ>>496の方法で会員テーブルの結合に会員IDを使ってしまうと、ある
会員の名前や住所が変更になると過去の注文分に関しても送り先の情報が
変更されてしまう。注文履歴の正しい管理という意味でこれは拙い。
なのでこういう場合は会員テーブルに代理キーを立てて結合条件にはこれを
用い、会員情報を変更する場合も古い行はそのまま残して新しい行を会員
テーブルに追加する方法で対応する場合が多い。
言葉だと説明し難いので、過去ログを参照するかサロゲートキーで検索して
欲しい。

いずれにしても、会員/非会員の注文頻度の割合(非会員の注文も多い場合は
>>493のデメリットは相対的に小さくなる)、会員情報の更新頻度、あと
は注文データの件数によると思う。
ストレージの無駄さえ許容できれば>>493は一番シンプルな解だと思う。
500NAME IS NULL:2011/03/19(土) 00:27:12.05 ID:???
そうか。顧客情報が変更になると注文情報も変更になるから
>>496だと整合性がとれなくなるよな。

>>493の方法は重複が出るけど、「過去○ヶ月のデータまで保存」
みたいな感じで、期限切れのデータは削除するかバックアップすれば
レコードの肥大化も極力抑えられる。
501NAME IS NULL:2011/03/19(土) 01:53:20.02 ID:???
>>497
しかし>>489は回答にすらなっていない。
要件についてツッコミも考察も入れず「○○パターンで出来るよね〜」
なんて真っ先にのたまうのは典型的なプログラマ脳だ。手元の技術しか
見えていない。
502NAME IS NULL:2011/03/19(土) 06:59:20.11 ID:???
「住所」が顧客の現住所(連絡先)なのか配送先なのか、はたまた配送先の
デフォルト値なのか、そういう分析がしっかりされないまま設計に入っても
議論がワヤになるといういい例だな。
503483:2011/03/19(土) 13:14:35.62 ID:jv8AI/hU
みなさんありがとうございました。助かりました。

会員の注文時の送り先住所は、
会員の住所が変わっても、変えてはいけないというのは盲点でした。

>>493の方法でいこうと思います。
これなら注文毎の住所が保存され、
会員の住所も保存できそうです。
会員の注文のときは、会員テーブルから住所をコピーして注文テーブルへ。
非会員の注文は、そのまま記載された住所を注文テーブルへ格納する。
という実装でいきたいと思います。
504NAME IS NULL:2011/03/19(土) 13:40:41.51 ID:???
>>502
それは設計しながらでいいんじゃねーの?
仕様書作りながら「これはこういう可能性があるからこうしよう」
みたいな意見が生まれるじゃん。483のやりとり見ても生まれてるわけだし。
505483:2011/03/19(土) 14:55:37.30 ID:jv8AI/hU
まてよ、
>>493
> ・注文テーブル (送り先の名前・住所入り)
> ・会員テーブル (会員の名前・住所入り)
この方法だと、例えば新たに「電話番号2」カラムを追加したいときに、
2つのテーブルをいじらないといけないので、保守性の面であまり良いと言えないかもしれませんね。。。

なので、
・テーブルX
 名前、住所などを入れるテーブル(名前が思いつかない。顧客情報テーブル?)
をつくって、
注文テーブルや、
会員テーブルからはテーブルXのIDを外部キーとして保存するという方法を考えました
(それが>>492の方法でしょうか?)
これなら新しい項目が増えても、テーブルXを1つ編集すればいいだけなので解決しそうです。
実装方法は>>503の方法と基本的に同じで、
新たに注文が発生した場合は、
・会員の場合
 テーブルXに保存されている会員情報を、
 新たにテーブルXのレコードとしてコピーして、このIDを注文レコードの外部キーとする
・非会員の場合
 テーブルXに入力値を保存
このような形でつくろうと思います。
またご意見をくださいますでしょうか。

>>504のおっしゃるとおり、一人で開発しているので、
つくりながら仕様も決めていくような方式をとっているので、小出しになっていたら申し訳ないです
506483:2011/03/19(土) 15:04:27.95 ID:jv8AI/hU
まとめると、
- 注文テーブル
 ・テーブルXのID(外部キー)
- 会員テーブル
 ・テーブルXのID(外部キー)
- テーブルX
 ・名前
 ・住所
 ・電話番号
    :
    :

この、テーブルXで名前住所などはすべて管理して、
あらたに会員が「届け先住所2」を追加したい場合は、
テーブルXに新しいレコードを追加して、そのIDを
会員テーブルの「届け先住所2」カラムに外部キーとして保存する、といった形になります。
507NAME IS NULL:2011/03/19(土) 16:00:36.14 ID:???
そもそも規模によっては住所2が必要ない場合あるぞ。
小規模、顧客1000人以下程度ならいらないと思うけどな。
必要な時に追加したら良いんだよ。
508NAME IS NULL:2011/03/19(土) 16:18:47.06 ID:???
会員と非会員の注文比はどれぐらい?
非会員の注文数が多いようだと住所項目等を別テーブルに
切り出すメリットはかなり減るよ。
509483:2011/03/19(土) 17:23:23.64 ID:jv8AI/hU
>>508
現行のショップは会員という概念がなかったので、
今回会員を実装してどれぐらい会員になるかは未知数ですね。
ただ、非会員で買い物をするメリットというはあんまり無いので、
(会員になってもパスワードという入力項目が増えるだけ/会員になると今後の住所入力不要)
会員になる人が多くなると予想はしています。
ただ本当に具体的な比率は未知数です。
510NAME IS NULL:2011/03/19(土) 18:10:41.88 ID:???
会員になる人が多いか否かは商品によるんじゃね?
Amazonのように購入ペースが多いなら会員登録するだろうけど、
電化製品や服とかは、会員登録しなくても買いそうだけどな。
511NAME IS NULL:2011/03/19(土) 18:12:40.61 ID:???
>>509
まず、

・会員情報に書かれる住所や名前や電話番号
・注文票に書かれる送り先の住所や名前や電話番号

ははっきり区別して考えた方が良いと思うよ。
例えば会員情報としては複数の住所や電話番号を持つことも
あるかも知れない。でもそれを全て注文票に転記する必要が
あるかというと、そうでもないと思う。

書かれている「新たに電話番号2カラムを追加したいときに」
の場合も、会員テーブルは変更する必要はあるかもしれない
けど、注文票にまで複数の電話番号を書き込む必要があるか?
というのは一度精査してみた方が良いと思う。
512483:2011/03/19(土) 20:12:44.29 ID:jv8AI/hU
>>511
たしかに。
やっぱり>>493がシンプルで良さそうだなぁ。
ぶれまくりですが、とりあえず先に進んでみようと思います。
また問題が発見してから考え直します。

みなさんありがとうございました。
513NAME IS NULL:2011/03/19(土) 21:26:29.97 ID:???
プログラマ脳はどこへ行った?
514NAME IS NULL:2011/03/20(日) 22:16:51.93 ID:77T4BkwY
エンティティとか主キーの概念がなくて
なんでも1テーブルに押し込む、キーはID列のみみたいなのはマジ勘弁
515NAME IS NULL:2011/03/20(日) 22:26:24.40 ID:???
>>514
大福帳テーブルは意外と重宝しますよ。
516NAME IS NULL:2011/03/20(日) 23:11:01.39 ID:???
>>515
うん。する。
517NAME IS NULL:2011/03/21(月) 08:13:31.36 ID:???
NoSQLの設計はまさにそんなかんじじゃない?
518NAME IS NULL:2011/03/23(水) 04:59:34.66 ID:???
.NETのコンポーネントの制限で複合キーを諦めざるを得ない
519NAME IS NULL:2011/03/23(水) 23:09:03.86 ID:MVHfXd/l
複合キーは無いわ
全テーブルにid int auto_increment でおk
520NAME IS NULL:2011/03/23(水) 23:27:16.79 ID:pi71qtr7
まさにプログラム脳
521NAME IS NULL:2011/03/24(木) 01:02:41.70 ID:???
>>519
つけるべきUNIQUE制約を忘れるなよ。
つけなければならない理由も。
522NAME IS NULL:2011/03/24(木) 14:48:10.96 ID:???
>>519
MySQL脳か。
523NAME IS NULL:2011/03/24(木) 22:24:42.09 ID:G0Glp4Mc
今一緒にデータ移行の仕事してる人は業務的には複合キーのデータでも
キー値を1つにマージした列をわざわざ作ってるんだよなあ。

なんでもJOINするときにマージした列でJOINした方が早いとかw

複合キーでもINDEX張ったりすれば遅くないですよって言っても信じてくれない。
524NAME IS NULL:2011/03/25(金) 04:20:43.76 ID:???
複合キーでもサロゲートでもいいが、キー値のマージは一番アホ設計だと思うw
525NAME IS NULL:2011/03/25(金) 04:42:34.88 ID:???
とりあえず日時型をキーに追加するアホが身近にいるので困る
526NAME IS NULL:2011/03/25(金) 04:51:01.91 ID:???
正規化崩しもそうだけど、解っていない人ほど「この方が速い」とか
キリッとのたまうんだよなぁ。
527NAME IS NULL:2011/03/26(土) 12:30:09.50 ID:???
会社マスタ
CompanyID(PK) , CompanyName
01           A社
02           B社
03           C社

支社マスタ
CompanyID(PK) , BranchID(PK) , BranchName
01             01      本社
01             02      埼玉支社
01             03      神奈川支社
(略)

例示した支社マスタみたいな複合キーが使えない場合、
どういうキーを振るのが普通なの?
CompanyID+BranchIDの連結でやってるけどダメ?
528NAME IS NULL:2011/03/26(土) 17:27:46.83 ID:???
ダメってことはないけど、CompanyIDとBranchIDを残してunique制約付けるなら
サロゲートキーは別に本来のキーと関係ある値にする必要はない。
529NAME IS NULL:2011/03/26(土) 19:35:25.40 ID:???
>>527
なぜ複合キーが使えないのかわからん
その例なら、CompanyIDとBranchIDの複合キーじゃないのか?

その例なら単にBranchIDを支社マスタ内で一意になるように振れば良いだけだと思うけど
530NAME IS NULL:2011/03/26(土) 22:15:51.71 ID:Ib5l6n2v
Companyコードはどこにあるの?
531NAME IS NULL:2011/03/26(土) 23:17:25.27 ID:U28l837d
>>527
システム以外の都合でIDが決まる場合が少ない確率ながらある
(ID=1を本社にしたいとか、支社IDを使い回すとか)から、
やっぱり複合キーじゃなくて
全テーブルにIDを振るのがいいと思うんだがなぁ
なんでこのスレの人は否定するのかね
532NAME IS NULL:2011/03/26(土) 23:50:53.54 ID:???
>>531
いや、普通に脳みそ足りなさそうな発想だから否定されて当然。

別に誰も代理キーを絶対に使うななんて言っていないでしょ。
要件をスキーマ設計に落とす過程で必要になった時に用法に注意
して使えば良いだけの話。
そのあたりをすっ飛ばしてトップダウンに「全テーブルにID振る」
なんて単細胞なアイデアを持ち出すから叩かれる。
533NAME IS NULL:2011/03/27(日) 05:15:34.98 ID:???
支社マスタ
BranchID(PK) , BranchName
  0101      本社
  0102      埼玉支社
  0103      神奈川支社

複合キーが使えないケースならこうせざるを得ないだろ
無関係なサロゲートキーでどうやって会社マスタとの紐付けを取る気だ
534NAME IS NULL:2011/03/27(日) 07:04:25.57 ID:???
サロゲートキーを使うならこうだろ。

BranchKey not null,
CompanyID not null,
BranchID not null,

primary key ( BranchKey ),
unique( CompanyID, BranchID )

「複合キーが使えない」というのが複数カラムのUNIQUEも使えないという
意味なら別だが。
535NAME IS NULL:2011/03/27(日) 15:12:06.00 ID:???
複合キーが使えないってのがどういうことかわからんが
おそらく
CompanyID(PK) , BranchID(PK) , BranchName
01             01      本社
02             01      本社

みたいなことを想定してるんだと思うが、それなら
支社マスタって書いてるテーブルが、支社のマスタと
会社と支社のリレーション持ってるテーブルを兼用してるのが間違いだろ
536NAME IS NULL:2011/03/27(日) 15:41:43.57 ID:???
それのどこが間違いなのかわからん。
537NAME IS NULL:2011/03/27(日) 15:45:16.49 ID:???
多分どっちでもいいんだよ。
どっちかしか駄目という人が間違ってる
538NAME IS NULL:2011/03/27(日) 16:19:08.97 ID:???
>支社マスタって書いてるテーブルが、支社のマスタと
>会社と支社のリレーション持ってるテーブルを兼用してるのが間違いだろ

なんで間違いなん?
539NAME IS NULL:2011/03/27(日) 17:25:52.72 ID:???
>>535
それが間違いだとして、テーブルを分けたとしても、その場合
会社支社リレーションのテーブルで同じ問題が起こる
そこが間違ってるかどうかは本質じゃない

じゃあ本質は何かっていうと
>複合キーが使えない場合、どういうキーを振るのが普通なの?
ってことだ
複合キーが使えない理由がよくわからんが、複合キーがダメなら代理キー作るしかないわな
代理キーの値をどうするかだが、ぶっちゃけ一意になれば何でも良いわけで
システム的に一意な連番振る機能があれば、それが使われることが多い
その場合は一意であることをシステム側で保障できるから
CompanyID+BranchIDの連結とかでもいいけど、その場合、それが一意かどうか
自分でチェックしないと保障されない
まあどっちにしろ要件的にCompanyID+BranchIDで一意チェックは必要だと思うから
この二つで主キーにしとけばシステム的に一意性が担保されるわけだが
540NAME IS NULL:2011/03/27(日) 19:55:32.48 ID:???
たいていの場合CompanyID+BranchIDが一意になるとは思うが
仮にCompanyIDないしBranchIDを変更することになった場合
キー値も変更しないと気持ち悪いことになる
541NAME IS NULL:2011/03/27(日) 20:09:12.32 ID:???
連番使った場合はCompanyIDとBranchIDから代理キーの値を得るのに
支社テーブル上で逆引きをする必要があるけれども、CompanyIDと
BranchIDの連結をキーにした場合はアドホックに文字列処理でキーの
値が手に入るという利点は一応あるw

ただそういう設計や運用はあまり見ないよなぁ。やはり勘所は複合キー
が使えないという理由がよく分からん事だと思う。
ORMマッパー使っているからとか、DBMSの実装上の制約とか、上司の
オッサンが決めてしまったコーディング規則でそうなっているとか、
理由ごとに必要とされる答えも微妙に違う気がする。
542NAME IS NULL:2011/03/27(日) 20:17:45.17 ID:???
>上司のオッサンが決めてしまったコーディング規則でそうなっているとか

これに500点
543NAME IS NULL:2011/03/28(月) 02:42:35.68 ID:???
いや、単純にコンボボックスのデータソースに出来ないからだよ
544NAME IS NULL:2011/03/28(月) 02:51:30.55 ID:???
CompanyIDを先に選択させりゃいいだろ
545NAME IS NULL:2011/03/29(火) 11:09:24.60 ID:1gjc3MDS
>>532
無知で悪いけど、
「全テーブルにID振る」
これのデメリットってなにがあるの?
546NAME IS NULL:2011/03/29(火) 13:14:53.99 ID:???
>>545
何の解決にもなっていないから。

連番をカラムとして追加してそれをテーブルの主キーにしたところで
「要件によって決まる」候補キーは歴然として存在するわけであって
そこに制約をつけたりアプリケーションのロジックを書いたりしないと
結局はデータの整合性は保たれないから。

「全テーブルにID振る」は実装上の方法論にすぎず、その前段階として
要件の分析をすっ飛ばすことは出来ない
ちゃんと分析をやった上で全テーブルに代理キー振るのなら、いいん
じゃない? ただその場合は当然分析の結果として必要な代理キーと共に
冗長な代理キーも見えてくるはずで、その評価は出来るよね。
547NAME IS NULL:2011/03/29(火) 16:32:09.66 ID:???
もう少し馬鹿にもわかりやすく答えてくれ
548NAME IS NULL:2011/03/29(火) 17:11:30.69 ID:???
全テーブルにID振ること自体は「無駄」以外にデメリット無いよ。
OracleのROWID疑似列みたいな例もあるわけだし。

ただそれを無批判に主キーとして用いるのにはデメリットというか
危険性がある。例えば自然キーが存在するのを忘れてUNIQUE制約
を付け忘れたため危険な重複タプルが発生したりとか、変更の可能性
が無い自然キーに対しても代理キーを用いることでトランザクション
表の更新時に自然キーから代理キーの値を得る無駄な逆引きが必要に
なったりとか。
代理キーを持ち込むことで検索はともかく更新は一般的に複雑に
なりやすい。

個人的には要件の見落としを防ぐ意味でも、まず初めに自然キーを
主体にしたスキーマ設計に落として、そこから必要に応じて代理キー
を導入するのが一番安全だと思う。
何度も言うけれども、自然キーはまず要件から決まるものだから。
549NAME IS NULL:2011/03/29(火) 17:54:47.01 ID:???
>表の更新時に自然キーから代理キーの値を得る無駄な逆引きが必要

いや別にいらんだろ
自然キーのユニークネスが保証されてるなら
550NAME IS NULL:2011/03/29(火) 22:02:11.24 ID:???
外部キーとして持つ場合なんかの話だろ
551NAME IS NULL:2011/03/30(水) 01:03:54.95 ID:???
CREATE TABLE tablename (keyid VARBINARY(50) , columnid VARBINARY(50) , value BLOB , PRYMARY KEY(keyid , columnid));
ですべてことたりる
552NAME IS NULL:2011/03/30(水) 01:56:16.14 ID:???
その分アプリのロジックで苦労するわけだけれどもね。
553NAME IS NULL:2011/03/30(水) 18:31:30.02 ID:???
>>551
ガリレオ・ガリレイ
554NAME IS NULL:2011/03/30(水) 23:04:14.47 ID:???
このスレと
【より良い】データモデリング【モデルを】
http://hibari.2ch.net/test/read.cgi/db/1057509675/
こっちのスレって何が違うの?
上流の作業の違いがいまいちよくわからん
モデリング後に設計?設計後にモデリング?
555NAME IS NULL:2011/03/30(水) 23:57:39.00 ID:1ro9g/Hl
住所の項目ってどうしてるよ?
都道府県と住所1と住所2(マンション名など)
って分け方が多いみたいだけど、
都道府県以外分ける必要ないよね
556NAME IS NULL:2011/03/31(木) 00:09:50.64 ID:???
>>555
たとえばタックシールや送り状を作成する業務を考えると
住所が適当な長さで2行になってる方が都合がいいだろ

業務要件で住所が2行必要ならDB上も2項目でもつのは普通
つまり分ける必要があるかどうかは要件次第
557NAME IS NULL:2011/03/31(木) 00:18:34.96 ID:P2ST+s4H
2行かどうかなんてアプリケーション側の問題なんじゃ?
558NAME IS NULL:2011/03/31(木) 00:40:24.56 ID:???
要件に二行で折り返すことが含まれているのであれば、どこで
折り返すのか区切りが解らないと困るじゃん。

改行入りの文字列を住所として突っ込むのもありだけど、住所と
マンション名その他に分けて二つのカラムに分けて入れることが
多いと思う。
559NAME IS NULL:2011/03/31(木) 00:40:37.54 ID:???
アプリケーション側の問題?
データモデルが常にそれらから独立していられるわけでもないだろう。
560NAME IS NULL:2011/03/31(木) 01:27:27.86 ID:???
>>555

+--id--+--henji--+--syugo--+--dousi--|
| 1 | YES  | I  | DO |
+----------------------------------+
561NAME IS NULL:2011/03/31(木) 20:36:43.35 ID:WO6NrX3S
>>555
> 住所の項目ってどうしてるよ?
郵便番号が取得できるなら郵便番号DBを利用する
できないなら総務省の地域コードを使う
コード変換できない番地以下は各レコードに持たせる
最低でもこうしないと話にならない
562NAME IS NULL:2011/03/31(木) 20:53:20.54 ID:???
DB的には住所をコード化するのが先決だわな

2行でタックシール(キリッ)とか馬鹿じゃねえの
563NAME IS NULL:2011/03/31(木) 21:52:14.51 ID:???
単に土地住所と建物住所じゃないの?
564NAME IS NULL:2011/03/31(木) 22:57:25.26 ID:???
タックシールの馬鹿を見るだけで、全角英数は馬鹿という定説が正しいことがよく分かる
565NAME IS NULL:2011/04/01(金) 00:06:20.96 ID:???
DB的には氏名をコード化するのが先決だわな
566NAME IS NULL:2011/04/01(金) 00:35:02.02 ID:???
「コード化する」ってなに?
567NAME IS NULL:2011/04/01(金) 00:42:28.28 ID:???
たっくんおかえり
568NAME IS NULL:2011/04/01(金) 00:48:36.32 ID:???
(国)、都道府県、市町村、町域、建物その他で分けるだろ
569NAME IS NULL:2011/04/01(金) 07:05:20.44 ID:QNKMILe9
郵便番号検索とかどうしてる?
新しい市町村増えたり、メンテが面倒そうなんだけど
570NAME IS NULL:2011/04/01(金) 07:09:15.74 ID:???
そうだよ。
だから郵便番号検索機能が仕様にある場合はメンテ分も見越して金額が跳ね上がらないといけない。
現実は「簡単でしょ?付けてよ」でプロジェクト終わり。
571NAME IS NULL:2011/04/01(金) 07:25:43.06 ID:???
要件確認せずに、「だろ」って決め付けてもねぇ。
地番は?住居表示はどうすべきだと思ってるの?
572NAME IS NULL:2011/04/01(金) 10:02:49.85 ID:???
初心者ですDBの勉強もかねて、簡単なユーザ登録のできるBlogサイト作成しようと思っています。
日記のデータを保存するテーブルについて質問なのですが、一般的(他のサイトなど)に日記を保存している
テーブルというのは、1つのテーブルで全ユーザの日記のデータを保存しているのでしょうか?
例えば一般的には、ユーザID,日付,日記本文,(その他省略)という構造なのでしょうか?

この場合、ユーザ数が増えれば相当なデータサイズになり、1ユーザの日記を数日分、selectするのに時間が
かかるような気がします。(この辺が初心者で、時間がかかるのかもよくわかってないのですが・・・)
573NAME IS NULL:2011/04/01(金) 11:09:31.44 ID:???
まぁそのためのデータベースだ
適切な設定なら100万レコードからでも一瞬で目的のレコードを探せるよ
574NAME IS NULL:2011/04/01(金) 22:51:49.57 ID:???
それだと、日記が一日ごとにしか書けないな。
575NAME IS NULL:2011/04/01(金) 22:54:03.22 ID:???
適当な質問には適当な回答しか無いだろ
576NAME IS NULL:2011/04/02(土) 02:10:35.17 ID:???
お前ら、こういうDB設計の要件定義って、
仕事でやる場合どのくらい時間かける?最低1ヶ月はかかるよね
577NAME IS NULL:2011/04/02(土) 02:18:13.66 ID:SR6eBDqn
>>570
そういう情報ってどっかにAPI公開されてないのかな
もしくはデータが簡単にダウンロードできたり
578NAME IS NULL:2011/04/02(土) 02:41:31.19 ID:???
>>577
データは郵便局サイトに
コンポーネントもググれば簡単に見つかる
大概↑データを使用する前提
579NAME IS NULL:2011/04/02(土) 09:09:49.55 ID:???
つーか、ろくすっぽ調べず「郵便番号メンテが面倒」とか、「住所は二行でタックシールだ!」
とかその手の足りない子を見ると、正規化だのサロゲートキーだのを熱く語る前に、他にやるべき
ことあんじゃねえのって感じだな
580NAME IS NULL:2011/04/02(土) 12:53:38.07 ID:???
なんか、面倒だな
581NAME IS NULL:2011/04/03(日) 15:32:48.21 ID:???
それでも地球はまわっている
582NAME IS NULL:2011/04/03(日) 17:10:43.94 ID:???
そして原発は冷却中である
583NAME IS NULL:2011/04/03(日) 23:20:21.80 ID:???
>>568
そんなの、実データ使った解析でいかようにもできる。
客が入力したままの文字列を一つだけ保持しておけば、あとは正規化した住所を都度アプリ側で吐き出せばいい。
584NAME IS NULL:2011/04/04(月) 00:39:15.82 ID:???
>>583
アプリに全部任せてDBは設計もクソもなくていいって聞こえるが・・・
585NAME IS NULL:2011/04/04(月) 00:47:44.84 ID:???
座標保持するのが流行り
586NAME IS NULL:2011/04/04(月) 06:56:16.69 ID:???
>>585
ダイレクトメールという文化はやがて滅びるから
企業の視点では、住所や所在地情報の地位は
低下し続けるに違いない。
587NAME IS NULL:2011/04/04(月) 07:51:03.48 ID:???
>客が入力したままの文字列を一つだけ保持

こんなこと書いてるエセ設計者の言うことは無視でよろし
588NAME IS NULL:2011/04/04(月) 19:32:50.57 ID:???
エセというか、ただの馬鹿だろ

せっかく公共団体の統一コードがあるのに文字列で持たせるとか正気か?
どうせAccessあたりで糞アプリ作ってる底辺プログラマだろけど
589NAME IS NULL:2011/04/04(月) 20:51:35.27 ID:???
DM用や顧客用のデータなんだろ?
正規化用のデータを、持しても客が使うデータは、たとえ間違っていても入力のママで使うんだよ。
現場も知らない馬鹿が教科書通りに設計すると回らないから気をつけろw
590NAME IS NULL:2011/04/04(月) 22:22:53.14 ID:???
正規化と言いたいだけの中小企業Access使いとか、底辺を見ても何の参考にもならないし、
時間の無駄だから、まともな知能を持った人は郵便番号DBや地方公共団体コードを使いましょー
591NAME IS NULL:2011/04/04(月) 22:23:08.98 ID:???
馬鹿にしてるつもりなのかな?拙い日本語使って煽られてもねぇ・・・
592NAME IS NULL:2011/04/04(月) 22:54:36.58 ID:???
ハンマーを持った子供には何でも釘に見える

地方公共団体コードなんて覚えたての子供は、「住所」と出てきたらコードを
使わなきゃ気が済まないんだよ。
593NAME IS NULL:2011/04/04(月) 23:40:02.69 ID:???
まあ、要件も確認せずに何とかコードでOKとか言うやつは
まともな知能を持ってないってのは解る

あと底辺の人ほど他人を底辺だって決めつけるよな
バカっていうやつがバカ的な感じ
594NAME IS NULL:2011/04/04(月) 23:46:14.17 ID:???
たっくんおかえり
595NAME IS NULL:2011/04/05(火) 00:53:48.93 ID:???
>>590
名寄せのロジックの一部には郵便番号DBも使うが、あくまでも一部。
おまえ、日本全国の何百万という重複する住所の名寄せなんてしたことないだろ。
したことがあれば、あんな不完全なデータを錦の御旗にドヤ顔出来る訳がない。
596NAME IS NULL:2011/04/05(火) 07:29:40.55 ID:???
>日本全国の何百万という重複する住所

具体例どぞ
597NAME IS NULL:2011/04/05(火) 07:33:04.51 ID:???
>>596
どこそこ区の青葉台となになに市の青葉台で一例。
この組合わせを合計するとそんな数になりそう。
598NAME IS NULL:2011/04/05(火) 08:24:56.02 ID:???
>>597
そういうのは都道府県が違うので重複とは言わない
もっと例示するにふさわしい具体例を挙げるよろし
599NAME IS NULL:2011/04/05(火) 08:53:52.43 ID:???
>>596
数十万単位のユーザーが十数年にわたって複数回入力する住所の名寄せだよ。
当然ユーザーからしてみれば同じ住所でも入力パターンは間違いも含め多岐に渡り、市町村合併や郵便番号も変わるからね。
600599:2011/04/05(火) 09:10:15.59 ID:???
他にも英語表記やカタカナ、ひらがな表記も含む。
市区町村の区分も守られておらず(特に町と村。そもそものインターフェースが郡で区切ってたりする)、都道府県が空白なんてざら。
複数のインターフェース、複数の時代を経た巨大な住所データなんて蓋を開ければこんなもん。
入力時に住所が正規化される単一のシステムならなんの問題もないけど、そうでない上記のようなデータなら、住所は一旦すべて連結し、解析掛けるのが正確で早い。
601NAME IS NULL:2011/04/05(火) 09:13:12.42 ID:???
だからコードにしておけば手入力を解析だ名寄せだとかキチガイじみた発想にならんのだって
ためしに通販サイトかなんか見てみろよ
大抵、プルダウンから選択か、郵便番号から選択だろが

逆に手入力のメリットがあるなら出してみろや
602599:2011/04/05(火) 09:24:48.43 ID:???
>>601
日本語分かるか?
入力時に正規化出来るなら問題ないがと書いてるだろ。
新規で開発するような話をしてるんじゃなくて、手書きも含め、複数のインターフェースが存在することが前提のデータ処理の話をしているんだが。
603599:2011/04/05(火) 09:28:14.95 ID:???
>>601
そして、コード化の一番のデメリットは過去の住所はにたいおうしづらい
604599:2011/04/05(火) 09:37:39.53 ID:???
>>601
失礼、途中で送信してしまった。

コード化のデメリットは過去のデータに対応しづらいという事。購入、決済データぐらいじゃそこまで気にする事はないし、下手すればそもそもの住所の正規化すら要らないケースが多いけど、
過去にさかのぼる名寄せみたいに、コード化よりも解析のほうが現実てきなケースがある事を知っておいて損はない。
605NAME IS NULL:2011/04/05(火) 18:49:22.35 ID:Ge8zwV8y
>>602
> >>601
> 日本語分かるか?
> 入力時に正規化出来るなら問題ないがと書いてるだろ。
名無しIDなしでお前のレスがどれだかわかるわけねーだろw
つーか、DB設計の話をしてるのに名寄せだ解析だとか言い出すから、
頓珍漢に拍車がかかるんだっての

データ移行が要件なら、その解析とやらに使う労力を変換に割り振れよww

言ってることが支離滅裂だっつーのw
606NAME IS NULL:2011/04/05(火) 19:31:24.00 ID:???
>>605
要するに何の話をしているんだい。
607599:2011/04/05(火) 20:05:05.66 ID:???
>>605
わざわざ599と入れてるのも分からない馬鹿かw
だから、DB構造としては、住所は一つまのカラムしかもってない(まあ郵便番号くらいは持つが)と言う事だよ。
一応、入力時は分割されてるが、それを連結したものが正式なデータとしてつかわれる。
正規家した住所は複数のカラムを持つが、それは都度都度の最新住所を吐きだすワークテーブル扱い。
高言う実例もあるんだよ。
608NAME IS NULL:2011/04/05(火) 20:20:17.47 ID:Ge8zwV8y
>>606
・住所をまんまの文字列で持つメリットは全くない
・文字列を保持して解析とか言ってるのは池沼
・名寄せとかいきなり言い出してるのは馬鹿(同じやつだろうけど)
・タックシール(キリッ

ちなみに文字列解析が現実的とか、噴飯ものの物を知らない子
みたいだけど、世の中にはコンバータってのが売っていてだな、
それで変換できないのは、対象外にするか、客先マターにするか、
その辺は契約にもよるけど、少なくとも俺らが住所と関わるって
のはそういうもんなの
いくら底辺プログラマで単価が安くても、アホな設計の尻拭いに
工数かけて解析とかありえねーよw
コンバータ買ってもらえって

とここまで書いたらタックシールが性懲りもなく現れた
もはや解読困難で相手にすんの面倒くさいから、他の人に任せる

といことで逃亡
609NAME IS NULL:2011/04/05(火) 20:22:29.70 ID:???
大変だなぁ。で、設計の話はどこ?
610599:2011/04/05(火) 20:50:16.33 ID:???
>>608
コンバーターは、それぞれの企業が自社で使う必要があって開発したものなことも知らないのか。
どんだけ小さな現場しか知らないんだよw
入力データを正規化して保持して、オリジナルを破棄出来るなら苦労はないんだよ。
自分の知らないしくみがあることは恥でもなんでもないのに、実例紹介してるのに信じないなら勝手にしろw
611NAME IS NULL:2011/04/05(火) 20:50:39.64 ID:???
変換ソフトの稟議書作成じゃね?
612NAME IS NULL:2011/04/05(火) 20:53:18.81 ID:???
>>610
設計の話しないなら帰れよ。
613NAME IS NULL:2011/04/05(火) 21:00:32.80 ID:r6xQc+hf
コンバータってこれか
http://www.addressmatch.jp/anormapp/do_anorm

昔住んでいた埼玉県大宮市高鼻町で検索したら、一発で変換できた!
オラ良いこと知ったぞ

でももう埼玉は住みたくない
614NAME IS NULL:2011/04/05(火) 21:20:38.76 ID:???
正直、なぜこんなのでこの人たちがここまで熱くなれるのか疑問ではある
615NAME IS NULL:2011/04/05(火) 21:28:27.96 ID:???
かつてクラス名簿を頼りに好きな娘の家の住所を探し歩いた経験からです
616599:2011/04/05(火) 21:31:55.96 ID:???
>>612
一応、設計上、住所がひとつの構造の実例もあるよ、という話だったが...
まぁ、確かにそろそろスレチだな。失礼。
617NAME IS NULL:2011/04/05(火) 21:37:41.55 ID:???
スレチ以前になんの参考にならないからもう出てこなくていいお(^^
618NAME IS NULL:2011/04/05(火) 23:55:16.74 ID:???
厳密に言えば設計じゃないのかも知れんが、要件定義、モデリングの話題としては興味深い。
619NAME IS NULL:2011/04/06(水) 00:54:23.79 ID:???
市町村コードと住所正規化コンバータの存在は確かにためになった
サロゲート談義よりよっぽど
620NAME IS NULL:2011/04/06(水) 09:28:28.56 ID:???
このスレ市町村コード知らない人が見てたのか
621NAME IS NULL:2011/04/06(水) 09:29:53.92 ID:???
>>620
私は公的なものは大嫌いだから。
622NAME IS NULL:2011/04/06(水) 09:42:58.98 ID:???
よくわからんけど、話題終了した方がよさそうなのはわかった
623NAME IS NULL:2011/04/06(水) 09:50:12.87 ID:???
>>621
ねっこのおりん
624NAME IS NULL:2011/04/06(水) 20:40:10.84 ID:???
「都道府県がなぜ北海道始まりなんだ!」と言われたらJISを参照する
625NAME IS NULL:2011/04/07(木) 16:18:49.41 ID:???
>>621
ただの馬鹿ですね
626NAME IS NULL:2011/04/07(木) 20:22:35.53 ID:???
まあ市町村コードなんて、馴染みのない人には全くない系統の知識だからね
いつなんどきどういう案件が降ってくるか分からないんだから、普段から
色んなことにアンテナを張っておくことが大切だってことさ
627NAME IS NULL:2011/04/08(金) 01:02:53.18 ID:???
> 色んなことにアンテナを張っておくことが大切だってことさ
> 色んなことにアンテナを張っておくことが大切だってことさ
> 色んなことにアンテナを張っておくことが大切だってことさ
> 色んなことにアンテナを張っておくことが大切だってことさ
> 色んなことにアンテナを張っておくことが大切だってことさ
> 色んなことにアンテナを張っておくことが大切だってことさ
> 色んなことにアンテナを張っておくことが大切だってことさ
> 色んなことにアンテナを張っておくことが大切だってことさ
> 色んなことにアンテナを張っておくことが大切だってことさ
> 色んなことにアンテナを張っておくことが大切だってことさ
> 色んなことにアンテナを張っておくことが大切だってことさ
628NAME IS NULL:2011/04/08(金) 04:33:07.53 ID:???
それで結論として、
住所はユーザが打ち込んだひとつの欄でいいね。
エラーがあるかとか、いろいろ解析するのが楽しみでね。
629NAME IS NULL:2011/04/08(金) 08:59:30.25 ID:UUNyLKi3
はいはい、タックシールタックシール
630599:2011/04/08(金) 09:52:11.62 ID:???
>>628
結論は、色々なケースがある、だろ。
住所一つ厨も、自分のケースは特殊と言ってたろ。
631NAME IS NULL:2011/04/08(金) 12:25:56.73 ID:UUNyLKi3
その場かぎりのアンケートみたいなのは使い捨てでいいんさ
顧客情報が絡んで将来的にDWH的な使い方がありえるんなら、
コード化にコストを費やすことを考えなくちゃならない
つか、そう提案すべき
632NAME IS NULL:2011/04/11(月) 17:06:53.99 ID:9HYaTenG
ちょっとご相談というかむしろどのような方法が一般的なのか判らない状態での質問です。

DBはSql鯖2008R2 アプリはC# WinFormで作成しています。

現在開発中物件で 営業時間・毎週休業日・祝祭日・臨時休業・臨時営業 の設定が必要なシステムを作成する事になりました。
今考えているのは各設定を年度毎にもち
確定された時点で1年分のカレンダーデータを一気に作成(1年分のレコードを作成)
修正された場合、修正日以降のカレンダーデータを変更する

ような感じで設計してみようと考えています。

カレンダーデータは

年月日
営業開始時間
営業終了時間
種別(0営業 1臨時営業 2定休 3祝日 4臨時休業 )

のような感じで1年分を作成し保持しようかと・・・

伝えたいことがうまく伝えにくいのですが、休日を柔軟に設定する事が出来て、
営業時間・休日のデータが簡単に取り出せる・判定できるようなテーブル設計を行いたいのです。

なんらかの定石的な方法があるのであればいいのですが、そのようなものは社内にないようでして・・・
何らかのヒント的なものでもいいので、お手すきの方がいらっしゃいましたらご教示いただければと思います。
633599:2011/04/11(月) 23:53:09.51 ID:???
>>632
種別が一つじゃ、臨時営業だけど、実は定休でなおかつ祝日の日とかどうすんだよw
種別は全部バラしてマスタにしろ。
それぞれの重み付けは固定ならアプリで持ってもいいし、変動するならこれもマスタにする。

634NAME IS NULL:2011/04/12(火) 00:25:33.31 ID:???
>>632
今考えてみた
T/種別( ID 名称 )
T/ルール( 月 日 曜日 何週 優先度 開始 終了 種別ID )
T/カレンダー( 年月日 開始 終了 種別ID )
V/カレンダー( 年月日 開始 終了 曜日@年月日 何週@年月日 種別ID )
カレンダーをデフォルト値で1年分生成してからルールを適用する

俺ならこうするかも知れない
635NAME IS NULL:2011/04/12(火) 07:21:40.99 ID:???
>>632
例えば、毎週休業日が年に三回変更になったとして、
そのルール・ログが残らないような設計はおかしい。

毎週休業日
---------------------------
休業日起点 | 休業日終点 | 曜日

というようなテーブルを定義していくべき。
636NAME IS NULL:2011/04/12(火) 10:01:08.49 ID:???
おはようございます。
>>633->>635
お時間を割いていただきありがとうございます。
皆さんの意見を参考に考え直してみました。
結果以下のような感じに・・・皆さんから見るとまだまだ設計力が足りませんが

TM_祝日(年月日{pk}、祝日名)
※祝日は基本固定なんで年更新処理で1月n週や固定日などから生成し、変更可能に

TM_毎週休業日(適用開始日{pk}、適用終了日{pk}、曜日番号{pk})
※休日は現在毎週n曜日のみでいいらしい。毎月n日とかその他のが出たらマスタ増やして対応

TM_臨時休業(年月日、備考[理由])
TM_臨時営業(年月日、営業開始時間、営業終了時間、備考[理由])

TM/営業時間(適用開始日、適用終了日、曜日、営業開始時間、営業終了時間)
※毎週土曜は半ドンらしくこういった持ち方もあり?

TM_カレンダー(年月日{pk}、{pk}に対する曜日、{pk}に対する第hoge週,営業開始(null有)、営業終了(null有)、備考)
※開始・終了のいずれかがnullなら営業してない(片方だけnullはありえない)
※備考は祝日\r\n臨時営業とかの情報をマスタ変更時に残すようにする

上記TM系のマスタ条件でカレンダーを生成
マスタ変更時は影響範囲のカレンダレコードだけを同時に書き換え
(優先度は 臨時営業>臨時休業>定休>祝日 カレンダーデータ作成時に固定となる)

TM_カレンダーは(年月日{pk}、{pk}に対する曜日、{pk}に対する第hoge週)だけを持ち、
ビューやストアドなどで結果を返すほうがデータの無駄が無いかもしれませんが、
参照の回数とかを考慮して少しデータ量が増えますがあえてテーブルに書き込むようにしてみました。

設計て難しい、でもこれしっかりやらないとアプリがグダグダになってしまうので
妥協範囲を出来るだけあげてキッチリやっておきたいです・・・
637634:2011/04/13(水) 00:29:50.20 ID:???
曜日、何週をビューで定義したのはバグとミスオペでの変更を抑える為
634の形ではルール適用で必要になるから持ってる
636の形はよく理解できてないけどあんまり必要じゃない気がする
ぱっと見TM_祝日はハッピーマンデー対応できない気がするけど毎年修正するのか?

>>635
毎週休業日の変更とかどの業種でもかなり大きい変更だから年数回どころか数年に1回だと思うけど
638NAME IS NULL:2011/04/13(水) 00:48:02.58 ID:???
>>637
TM_祝日は基本年次処理でつどつど祝日をyymmddで保持するっぽいから、ハッピーマンデーも問題ない気がする。
639NAME IS NULL:2011/04/13(水) 00:57:50.12 ID:???
>>638
そこでやるのか〜
ずいぶん高度だな
640NAME IS NULL:2011/04/13(水) 05:27:11.25 ID:???
>>639
高度というか、力技だな。単純だがそれがいい。
管理者も入れ替わり、運用がおざなりになったときに、日付の入力を忘れたり間違えたりして支障が出る可能性は高そうだがw
641NAME IS NULL:2011/04/13(水) 09:51:31.28 ID:???
>>637-640
色々なご意見ありがとうございます。

>>637
いや、正直日付から週数や曜日は簡単に出るんですが、試しに入れてみたらそのデータがあるとDBを生で見たりする場合に
判りやすじかったのでパクらせてもらいました。

祝日に関してですが
年次更新時にデフォルトできっちりデータは入れてやります。(全て入力とかは間違えるし厳しいと思うので)
その為にプログラム内で1月1日は元旦、1月の第2月曜日は成人の日などの情報を持ち
その情報からレコードを作成してやります。

基本的に祝日定義や名称の変更があるんでその部分をDLLなり設定ファイルなりにして
変更時にアップデートでファイルの差し替え、年次更新時にそのデータ利用して一覧を作る
という感じです。
祝日の定義が変る可能性が非常に高いので、もし何らかの理由でこちらの対応が間に合わない場合、
何かユーザー側での変更可能な方法が必要かなと思いベタベタな実装にしました。
(今の政府は年度開始時に年度末の休日定義とか平気で変えてきそうなので・・・)
※地方によって祝日定義変わるとかホント勘弁してください。 ほんと苦肉の策です ありがとうございました。

後他の入力に関してですが
正直オペミスはあるとおもいます。なので入力チェックとかキツキツにする必要はあると思います。
(年次更新時に定義の範囲が今年度にかぶってない場合は出来ないとか)

PS.
仕様書・設計・レビュー・PG・デバッグ・設置と納品まですべて一人でやらなきゃいけないので頭が沸いてきました。
642NAME IS NULL:2011/04/13(水) 10:00:34.82 ID:???
>プログラム内で1月1日は元旦、1月の第2月曜日は成人の日などの情報を持ち
>その部分をDLLなり設定ファイルなりにして
なぜそれをDBに格納しないのかね
643NAME IS NULL:2011/04/13(水) 10:14:53.39 ID:???
>>642
年次更新のタイミングでその情報をDBへ格納します。
定義が変る可能性が高いので年次でギリギリまで登録待ってから登録→もし年内で変更あれば手動で変更
という予定です。
644NAME IS NULL:2011/04/13(水) 23:30:26.66 ID:???
ハッピーマンデーも将来無くなる可能性がある。

祝日をyyyy/mm/ddで持つのもありだね。
645NAME IS NULL:2011/04/14(木) 20:42:54.35 ID:2zZWkF3S
>>643
その年が変わってから、
その年の休日が変わる可能性なんてないよw
646NAME IS NULL:2011/04/14(木) 20:55:04.90 ID:???
>>643
>定義が変る可能性が高いので
変わる可能性が高い情報をプログラム側に持たすのか?
休日の定義もDBにもたせて、その定義から年次更新でマスタ作成すればいいだろ
647NAME IS NULL:2011/04/14(木) 21:18:24.25 ID:???
休日の定義を持たせたら、その休日の定義の有効期間まで保持しなきゃならなくなる。
だったら、素直にyymmddで休日を持たせたほうが話が早い。
648NAME IS NULL:2011/04/14(木) 22:15:42.63 ID:???
過去となった祝日は絶対に不変なのだから、yyyy-mm-ddで決め打ちでいいと思うけどな〜
649NAME IS NULL:2011/04/14(木) 22:51:22.94 ID:???
祝日どころか全部過去適用なしなんだから有効期間ってのがなぜ必要なのか意味が分からない
単に、ルールで持てば?展開して日付で持てば?って話のような気がするけど
650NAME IS NULL:2011/04/14(木) 23:07:13.39 ID:???
>>649
例えば、極端な話、元日が1月1日ではなく、1月10日に変更になったとする。
当然、過去の1月1日には適用できないので、いつから元旦が1月10日になったのか日付を保持する必要があるだろ。
651NAME IS NULL:2011/04/14(木) 23:11:40.13 ID:???
別にないよ。
2010/01/01
2011/01/10
って持っとけばいいだけだから。
652NAME IS NULL:2011/04/14(木) 23:17:29.01 ID:???
>>651
だから、それでいいじゃん、と言ってるわけだ。
休日のルールを定義づけして、DBで保持する必要はない。
653NAME IS NULL:2011/04/14(木) 23:57:19.08 ID:???
>>650
ごめん、>>646の解釈が全然間違ってて見当違いなレスした

生成よりも反映でやった方が色々いい気がするけどなぁ
延々増え続ける祝日テーブルとか嫌だわ、俺は
654NAME IS NULL:2011/04/15(金) 00:20:06.76 ID:???
おめーの好き嫌いはどうでもいい
655NAME IS NULL:2011/04/15(金) 00:54:12.36 ID:???
>>654
ちょっと笑ったw
それにしても、ID出ないと議論もまともにし辛いね。
IDなしでもOKの理由ってなんかあるんだっけ?
656NAME IS NULL:2011/04/15(金) 05:30:37.26 ID:???
>>653
反映ってのが、ルールを動的に適用するって言う意味なら
ハッピーマンデーや春分の日を動的に適用するのが難しい
逆に、定休日の変更とか考えると動的に適用する方がいいかもしれん
ただ、生成にしても反映にしても、過去分切り捨てないなら
延々増え続けるのに違いはないと思うが

生成あるいは反映されたカレンダーをどう使うかにもよるだろうけど
変更の頻度とカレンダーを使う際のパフォーマンスとか考えると
俺なら適当なタイミングで生成する
657NAME IS NULL:2011/04/16(土) 00:12:24.94 ID:???
まさに今度の案件で、FROM年月日、TO年月日で営業日やそれ以外を保持する必要が出た。

祝日などは FROM:2011/01/01 TO:2011/01/01 名称:正月
658NAME IS NULL:2011/04/16(土) 16:59:35.02 ID:???
夏休みでもないと1日単位の方が効率的な感じだな
659NAME IS NULL:2011/04/16(土) 17:41:05.38 ID:???
こういうテーブルは差集合を取るために使うことが多いしな。
1日1レコードの方が何かと無難に思える。
660NAME IS NULL:2011/04/17(日) 09:08:09.05 ID:???
ここのスレのひとたちのレベルとは違いすぎるんで恐縮なんですが、、、
インデックスって何に設定するのが良いんでしょうか。
たとえば、掲示板の投稿テーブルとかだとなににインデックスを設定したらいいでしょうか
661NAME IS NULL:2011/04/17(日) 09:13:32.97 ID:???
検索キーに張ればいいよ。
662NAME IS NULL:2011/04/17(日) 09:31:24.55 ID:???
>>661
検索対象となりえるフィールドってことでしょうか。
今は名前と、本文メッセージで検索できるようにしてるので、
それらにINDEXつけたらいいのかな?
663NAME IS NULL:2011/04/17(日) 09:35:35.93 ID:???
名前はアリだろうけど、本文メッセージはインデックスの意味ないだろうね。
664NAME IS NULL:2011/04/17(日) 09:59:15.72 ID:???
>>663
文章が長すぎるからですか?

あと、
postテーブル (投稿
tagテーブル (タグ
こういう2つのテーブルがあるとして、
postテーブルに複数のtagがつくような場合(多対多であってますか?)
postとtagを結びつけるテーブルが必要だと思いますが、
このテーブルの名前がいい感じのが思いつきません・・・。
みなさんこういうテーブルは何テーブルと名づけてますか?
post_tag_relation
とかかな?
665NAME IS NULL:2011/04/17(日) 11:55:47.26 ID:???
テーブル名はそのものズバリの短い名称ならなんでもいい、SQLでの記述量が全体的に減る。
短くなるならローマ字表記もありだと思う。
666NAME IS NULL:2011/04/17(日) 12:58:08.73 ID:???
>postとtagを結びつけるテーブルが必要だと思いますが、
そもそも直に結び付かないのがなぜかと問いたいが。
関係性が複数あってアナリシスパターンみたいに知識レベルと操作レベルに分けたいならともかく。
667NAME IS NULL:2011/04/17(日) 13:26:25.07 ID:???
>>665
短縮しようとすると必然的に漢字になる。
668NAME IS NULL:2011/04/17(日) 13:58:57.30 ID:???
>>666
postテーブル
id title name message
1 投稿テスト ななし てすです。

tagテーブル
id name
1 タグ1
2 タグ2

post-tagテーブル(ナイスなネーミングが思いつかない)
id post_id tag_id
1 1 1
1 1 2


表にするとこんな感じです。
3つ目のテーブルがないと結びつかないと思いますが・・・できます??
669NAME IS NULL:2011/04/17(日) 15:01:12.87 ID:???
いや、あってるよ。
それと、本文を高速に検索するには形態素解析とか別の技術がいる。
670NAME IS NULL:2011/04/17(日) 15:05:04.50 ID:???
>>669
ありがとうございます。
え、%LIKE%でやってて、全く問題なく動いてるんですけど、
書き込み数が少ないからいけてるだけなのかな
671NAME IS NULL:2011/04/17(日) 17:00:42.33 ID:???
LIKE句で早いかどうかはDB側のエンジンに依ると思います。
672NAME IS NULL:2011/04/17(日) 17:19:18.92 ID:???
ネーミングは、『R_投タ』だろ?
673NAME IS NULL:2011/04/17(日) 17:31:36.42 ID:???
件数とフィールドサイズ次第じゃね?
674NAME IS NULL:2011/04/19(火) 00:35:20.25 ID:???
1 業務の区分番号で自然キー設計した
2 削除履歴も残したくて削除フラグを作った(行を複製して削除=1する)
3 削除フラグを立てた行を作るとキーが二つになってしまう!
4 履歴を沢山もてるように削除日を作った
5 (自然キー + 削除フラグ + 削除日)で複合キーに変更した
6 履歴行を除くためテーブルを結合してからwhere句で削除フラグ=0することに
7 クエリを10段階くらいネストしてモリモリ書く
8 なんかデータが欠落してると思ってたら、INNER JOINしてることに気が付く
9 手の施しようがなくなって俺のとこにお鉢が回ってきた


こんなデータベース管理したくねーよカス。だから女は嫌いなんだ
675NAME IS NULL:2011/04/19(火) 08:28:01.29 ID:???
>>674
8はたしかにバカだけど、ほかはまあ
しかたないんじゃね?
676NAME IS NULL:2011/04/19(火) 15:53:11.76 ID:???
てか別に手の施しようがなくなってもない気が
677NAME IS NULL:2011/04/19(火) 21:02:38.78 ID:???
クエリ10段階程度は、普通とは言わないけどたまにあるなー。
インデックスちゃんとはってたら結構パフォーマンスも出るし
678NAME IS NULL:2011/04/21(木) 07:14:14.64 ID:???
> (行を複製して削除=1する)
なんで複製するの?
679NAME IS NULL:2011/04/21(木) 11:13:26.69 ID:???
思うに区分番号を使いまわしたいんだろう
つまり、もともとも区分番号は候補キーじゃなかったって話で、
1から間違ってるってことだな

ただ、
>(自然キー + 削除フラグ + 削除日)で複合キーに変更した
らしいので、別にそれで何とかなるだろって話

そこは自然キーじゃなくて区分番号だろうと突っ込みたいが
>>674は区分番号がキーじゃないとちゃんと解ってるのかね
680NAME IS NULL:2011/04/21(木) 17:50:16.56 ID:???
何のテーブルとどう結合したのかよくわからんのだが、削除日だけだと
日付が絡んだ結合がかなり複雑になりそうな気が。
作成日も加えるとか、それこそサロゲートキー導入か。
681NAME IS NULL:2011/04/21(木) 17:55:47.87 ID:???
削除した事実と日付、元データのログだけなら、削除テーブルに退避させるだけでいい。
682NAME IS NULL:2011/04/21(木) 21:31:10.43 ID:???
>>678
よくわからないが、同一テーブル内に履歴があれば管理
しやすいと思った形跡がある。。テーブル開いてすぐ下に
履歴があるので、どう変更したか見やすいとか。

>>679
×(自然キー + 削除フラグ + 削除日)で複合キーに変更した
○(区分番号 + 削除フラグ + 削除日)で複合キーに変更した

書き間違い。すまそ

>>680
最初からそうしとけと

>>681
普通の人間が考えればなそうだな。考えたやつが普通の
人間じゃないから困る。
683NAME IS NULL:2011/04/21(木) 22:10:23.27 ID:???
ログ管理用のテーブル設計の難しさは異常
684NAME IS NULL:2011/04/29(金) 00:43:58.61 ID:???
DB設計のコツは、「難しく考えるな。あきらめろ!」
685NAME IS NULL:2011/05/01(日) 01:24:07.02 ID:???
>>683
何が難しいの?よければ要件を教えて。
686NAME IS NULL:2011/05/02(月) 10:42:57.33 ID:???
>>683じゃないけど、全文検索のこととか考え出して、行き詰まってんじゃないの
687NAME IS NULL:2011/05/02(月) 17:27:10.54 ID:Ym6L+dps
モデリングの勉強をしているのですが以下のような場合、どんなモデルになるでしょうか?

商品の卸売のようなシステムで

1.顧客からはは随時、受注がくる
2.ある時点で、受注を束ねて、顧客商品別に発注先に発注
3.発注先が直接顧客へ商品を配送して、完了報告をしてくる

という業務フローです。
自分のシステムでは、受注を受けるだけで、出荷は商品ごとの発注先任せといった感じです。

よろしくおねがいすます
688NAME IS NULL:2011/05/02(月) 17:33:37.85 ID:???
商品マスタと
発注先マスタと
受注テーブルを用意して適切に紐付け

任意のタイミングで商品別に集計出して発注アクション
その時に受注テーブルにあるレコードに発注済みフラグを立てる

おしまい
689NAME IS NULL:2011/05/02(月) 17:46:15.64 ID:???
1つの受注には、いくつかの商品があり、その商品は発注先はバラバラです。

受注:キー 受注番号 非キー 顧客番号、配送先住所
受注明細:キー 受注番号、受注明細番号 非キー 商品番号、数量、発注先

発注:キー 発注番号 非キー 発注先、顧客番号、配送先住所
発注明細:キー 発注番号、発注明細番号 非キー 受注番号、受注明細番号、商品番号、数量

リレーションは
受注:受注明細 1:N
発注:発注明細 1:N
受注明細:発注明細 1:1

発注まではこんな感じだとおもっています
690NAME IS NULL:2011/05/03(火) 00:29:54.01 ID:6I8m/Wta
>>689
なぜ、「配送先住所」が「受注」と「発注」の両方にあるの?
なぜ、「数量」と「商品番号」が「受注明細」と「発注明細」の両方にあるの?
よく分からない。
691NAME IS NULL:2011/05/03(火) 00:35:37.80 ID:???
>>689
一つの「顧客」は、一つの「配送先」を持つの?
それとも、一つの「顧客」は、複数の「配送先」を持ちえるの?

全ての受注は必ず発注されるの?
仮にそうだとした場合、
「商品番号」が決まれば「発注先」は自然と決まるの?

このあたりがはっきりしないと答えがだせないよ。
692NAME IS NULL:2011/05/03(火) 01:05:27.07 ID:???
>>687
メインのフローは馬鹿でもできるから、適当に組んでもみんなほぼ同じモデルになる。
ちゃんと考えなきゃいけないのは、返品、誤配送、破損、誤発注、キャンセル、郵送先変更、在庫切れなどの例外処理のフロー。
693NAME IS NULL:2011/05/03(火) 03:49:27.10 ID:???
>>692
勉強って書いてあるべさw
そこまで細かくやらんでしょ
694NAME IS NULL:2011/05/11(水) 23:35:39.63 ID:+dDfImqi
サロゲートキーってのは調べてみると
「ユーザーが認知しない、業務的に意味をなさない連番とかのキーにせよ。」というのは理解したんだが
このサロゲートキーは検索画面の条件や帳票項目とかに利用していいのかしら?

ユーザーが認知しないという意味では、利用してはいけない気がするが
たとえば業務的な採番ルールがない(ただの歯抜けOK連番とか)伝票番号の場合
システムでは検索条件にもなるし出力項目として利用されていると思う。

この場合、伝票番号とは別にサロゲートキーを持つのか否か。どうおもう?
695NAME IS NULL:2011/05/11(水) 23:57:54.25 ID:???
迷うまでもなく持つわ
696NAME IS NULL:2011/05/12(木) 00:19:14.93 ID:???
>このサロゲートキーは検索画面の条件や帳票項目とかに利用していいのかしら?
いい。サロゲートキーにする意味は、未来永劫不変で一意であることを保証することだから、
IDとか識別番号とかいう名前で利用することはある。

>この場合、伝票番号とは別にサロゲートキーを持つのか否か。どうおもう?
伝票番号が一意のサロゲートキーになるならどっちでもいい。
697694:2011/05/12(木) 00:37:27.98 ID:???
どうもです。

>696さんの意見はしっくりきました。
>695さんの、迷うことなく持つの理由は

>いい。サロゲートキーにする意味は、未来永劫不変で一意であることを保証することだから、
がユーザーが認知することで崩れるから。ということかな?

ユーザーが認知すると、ユーザーの使い勝手で「伝票番号に日付入れてくれ!」とか言われたら
未来永劫不変で一意であることを保証できんな
698NAME IS NULL:2011/05/12(木) 00:45:57.64 ID:???
伝票に日付、アルファベット、ゼロ埋めはザラにある変更
699 忍法帖【Lv=22,xxxPT】 :2011/05/15(日) 16:22:26.09 ID:???
a
700NAME IS NULL:2011/05/15(日) 20:33:01.83 ID:???
>>697
キーの一意性が変わるような変更に対して、サロゲートキーが対策になる
なんて思っていたら痛い目見るよ。
701NAME IS NULL:2011/05/15(日) 21:08:57.72 ID:???
> キーの一意性が変わるような変更
702NAME IS NULL:2011/05/16(月) 00:34:01.57 ID:???
「未来永劫不変で一意であることを保証」できなくなるような変更のことだろ。
703NAME IS NULL:2011/05/16(月) 03:35:54.10 ID:???
>>700
キーって何のことだ?主キー?候補キー?

候補キーが、候補キーじゃなくなるような変更がありえるなら
(その前提がある段階で候補キーかどうかあやしいが)
その候補キーを主キーにしないでサロゲートキーを使うのは対策になるわけだが
お前の言う痛い目ってどんな事なんだ?
704NAME IS NULL:2011/05/16(月) 05:15:31.90 ID:???
>>703
主キーを追加しなくてはならなくなることだろう。
705NAME IS NULL:2011/05/16(月) 07:17:25.05 ID:???
>>704
サロゲートキーを使うっていうことは
当然そのサロゲートキーが主キーになってると思うんだが

サロゲートキーの一意性が保証できなくなるって話なのか?
706NAME IS NULL:2011/05/16(月) 21:00:42.81 ID:???
そんな風にシステム内部で発行する人工キーだけが唯一の候補キーになっているテーブル
だらけで、投入するデータがinsertされるべきかupdateされるべきかわけがわからない状態に
なってしまったシステムは見たことがあるな。
キーが無いのと同じことなんで、注意深くやらないと破綻するのは目に見えているんだけどね。
707NAME IS NULL:2011/05/16(月) 22:50:38.28 ID:???
>>706
> 投入するデータがinsertされるべきかupdateされるべきかわけがわからない状態に

サロゲートキー関係なくね?
708NAME IS NULL:2011/05/16(月) 23:00:41.81 ID:???
関係ないよ。
「サロゲートキーで一意性を保証」するから大丈夫なんて言えない例。
709NAME IS NULL:2011/05/16(月) 23:20:15.18 ID:???
魔法じゃないんだから、サロゲートキーに何期待してるんだよ (w
710NAME IS NULL:2011/05/17(火) 00:07:43.44 ID:???
>>708
いいえ
バカ除けを施しても破綻させちゃう逸材が居る限り大丈夫なんて言えない例です
711NAME IS NULL:2011/05/17(火) 05:33:39.34 ID:???
なんで、このスレのやつってサロゲート談義が大好きなん?
712NAME IS NULL:2011/05/17(火) 06:47:19.90 ID:???
バカ除け?サロゲートキーしかキーが無いテーブルがバカそのものじゃん。
713NAME IS NULL:2011/05/17(火) 16:17:28.35 ID:???
馬鹿寄せ呪文「サロゲート!」
714NAME IS NULL:2011/05/17(火) 18:27:09.25 ID:???
サロゲ廚、自重しろ
715NAME IS NULL:2011/05/17(火) 21:15:26.73 ID:???
fjのmalloc/free論争みたいなもんだな。季節の風物詩。
716NAME IS NULL:2011/05/18(水) 00:23:53.39 ID:???
>>706
イメージできないから具体例あげてみて
717NAME IS NULL:2011/05/18(水) 22:46:57.11 ID:0/HKB1af
このスレで使われている「主キー」という言葉は、
ほとんどの場合「候補キー」のことだよね?ww
718NAME IS NULL:2011/05/19(木) 00:09:24.95 ID:???
>>716
(ID,NAME,VALUE)というテーブルがあって、IDがシステム内部で生成するキーで
これが唯一の候補キーだとする。ここで
(1,'田中',100)
(2,'田中',200)
というレコードが既に存在している状態で新たに('田中',300)というデータを
テーブルに反映させるとする。
このとき、ID=1を更新すべきかID=2を更新すべきか、あるいはID=3として
追加すべきか?
719NAME IS NULL:2011/05/19(木) 00:26:28.66 ID:???
田中,300じゃ。IDがNullじゃん。
そんなデータ、入力段階でエラーにしろw
他の例を。
720NAME IS NULL:2011/05/19(木) 00:37:03.31 ID:???
IDは自然キーじゃないんだからシステム側で発行しなきゃならんだろ。
721NAME IS NULL:2011/05/19(木) 02:51:10.85 ID:???
>>718
それは業務要件によってきまるのであって、データモデルで決まるのではない
指定した行を更新する必要があるなら、行を特定する必要があるだけで
その特定が他のテーブルとの結合によるが、そのテーブルに自然キーがなければ
サロゲートキーが必要になるだけ

ちなみにこの例で、このテーブルだけみてID1を更新すべきかID2を更新すべきか判断できるなら
(NAME,VALUE)が候補キーでないと話がおかしいんだが
722NAME IS NULL:2011/05/19(木) 06:59:39.36 ID:???
だから、「サロゲート」キーで一意性を保証していたとしても
それだけじゃあ何も解決しない例なんだが。
723NAME IS NULL:2011/05/19(木) 09:42:50.09 ID:???
>>722をプロジェクトから外せば解決するんじゃね?
724NAME IS NULL:2011/05/19(木) 23:49:20.97 ID:???
反論はできないけど、やり込められたままじゃ業腹だから何か言い返したいw
725NAME IS NULL:2011/05/20(金) 06:32:31.26 ID:???
DB設計とは無関係。
はい論破
726NAME IS NULL:2011/05/20(金) 08:59:41.59 ID:???
>>722
サロゲートキーで一意を保証していれば、
そのキーを使って他のテーブルと結合することで判断できる(可能性がある)
他に候補キーがなければ、サロゲートキーでしか結合できない

つまり、サロゲートキーがあるおかげで判断できるようになるんだから
サロゲートキーで解決する事象ですが?
727NAME IS NULL:2011/05/20(金) 09:39:04.99 ID:???
もうさ、サロゲートキースレでもつくってそっちでやれよw
728NAME IS NULL:2011/05/20(金) 10:59:11.66 ID:???
私には>>721が言い得て妙、という気がするのだが、違うのかな。
729NAME IS NULL:2011/05/20(金) 21:47:21.09 ID:dCbPz/cP
というか、サロゲートキーについて、一言言わせて欲しいんだけど、
連番・・・とか、ID・・・とか、意味不明な名前ではなくて、
それが単なる連番だったとしても、〇〇番号・・・みたいに、何かしら意味の通る名前にして、
それを表(画面とか)にだしたほうが絶対、設計的にも利用者的にも優しいと思うんだけどね。

それをやると、もうサロゲートキーの定義から外れるのかもしれないけど。
730NAME IS NULL:2011/05/20(金) 22:52:26.97 ID:???
>>726
結合先のテーブルに本来のキー(サロゲートキーが代替する被代替キー)が
存在するという前提ならば、サロゲートキーを使わなくても解決できる話なんだが?
731NAME IS NULL:2011/05/20(金) 23:38:03.66 ID:???
他に候補キーがなければって書いてあるぞ
732NAME IS NULL:2011/05/20(金) 23:55:41.58 ID:???
他に候補キーがない2つのテーブルでの話?
だとしたら1テーブルの話と同じじゃん。結合したからといって何も変わらない。
733NAME IS NULL:2011/05/21(土) 00:56:11.72 ID:???
>>718
なにがしたいのか全然わからんなw
でもサロゲート無かったら、
田中,100
田中,200
みたいな主キーが無いテーブルになるんでしょw
サロゲートあるほうが、マシじゃ無いの?
734NAME IS NULL:2011/05/21(土) 01:11:55.35 ID:???
キーが存在しないことが問題であって、それに形式的なキーを追加しただけで
何かが改善すると思うことが間違い。
735NAME IS NULL:2011/05/21(土) 02:22:32.41 ID:???
キーが存在しないことだけが問題なら、サロゲートキーで解決する
キーが存在しても意味がないなら、サロゲートキーも意味がない

>>718は後者な
736NAME IS NULL:2011/05/21(土) 02:29:50.61 ID:???
スレたてて他所でやってよ
信者がいる訳でもないのにそこまで必死に否定することもないだろうに
737NAME IS NULL:2011/05/21(土) 07:48:47.82 ID:???
>>736
どうせ他に話題も無くて過疎ってるのに、なぜそんなに嫌がる
738NAME IS NULL:2011/05/21(土) 10:47:16.66 ID:???
>>735
なんだ?キーが存在しても意味がない場合って。
739NAME IS NULL:2011/05/21(土) 11:55:39.82 ID:???
なんか設計ミスをどうフォローするか、
と言っているようにしか見えない。
740NAME IS NULL:2011/05/22(日) 03:15:58.77 ID:???
ミスというか、718の例でどちらかの行しか更新してはいけないなら
キーをつけろとしか言い様がない
741NAME IS NULL:2011/05/22(日) 09:13:00.78 ID:???
そのキーが問題なんだろ。>>718は一応キーが付けてあるわけだし。
742NAME IS NULL:2011/05/22(日) 10:58:09.78 ID:???
一応キーが付いてるのであれば、
反映するデータが('田中',300)じゃ足らんでしょ、対象のIDもくれなきゃ

743NAME IS NULL:2011/05/22(日) 11:17:17.46 ID:g3or/Rum
>>718は、もう少し業務を説明してよ。

(1,'田中',100)
(2,'田中',200)

「1」、「2」はシステムが自動で採番するキーだということは分かった。
「田中」、「田中」っていうのは、人の名字だと思うんだけど、1行目と2行目は同一人物なの?
田中だけなら、同一人物でない場合もあり得るよね?w
「100」「200」っていうのは具体的に何の数字なの?w

これはどういう単位で何を管理している、どういうテーブルなの?
全く意味が分からない。

こんな状態(情報がほとんどない状態)で、あるべき設計を語るなんて、できるわけが無い。
だから不毛な議論になる。

サロゲートキー云々以前の問題。
744NAME IS NULL:2011/05/22(日) 12:18:02.34 ID:???
そういう分析がないとわけがわからないだろ?
そういう状態で、キーがないからといって連番のキーを追加して「これで一意を
保証できる」なんて言ってもなんの解決にもならないわけだ。
語っているのは「あるべきでない」設計の方。
745NAME IS NULL:2011/05/22(日) 14:30:52.75 ID:???
>>744
何がいいたいのかわからないが、詭弁に聞こえる。
746NAME IS NULL:2011/05/22(日) 14:44:42.05 ID:???
>>742
そのIDをどこから得るかっつー話だ。
747NAME IS NULL:2011/05/22(日) 16:31:38.44 ID:???
大体IDが主キーなんだから更新ならIDでどれかを指定してこなきゃ。
ID無しで更新か挿入かわからないで「反映させる」って言ってる
時点で何かおかしいよ。この例ではIDを何にも使ってないんじゃ。
例えるなら、安全のためにブレーキを付けたけどブレーキを踏まず
事故りましたみたいな。
事故ったからブレーキは不要みたいな三段論法で攻めてくる人も
頭がおかしいよ。
748NAME IS NULL:2011/05/22(日) 17:32:39.14 ID:???
まぁ根元の>>706からしておかしかったからな
人工キーを採用してるのに
このタプルに人工キー割り当てたかどうかわかりませんけどよろしくやってください
なんて言ってきたらぶち切れるわ
749NAME IS NULL:2011/05/22(日) 17:51:00.13 ID:???
だから、キーがない/特定できないテーブルに一意のIDを付けたところで、
それだけで何か改善するわけじゃない。最初から言っていることなんだがな。
>>747
「ブレーキは不要」じゃなくて「それはブレーキじゃない」だな。
750NAME IS NULL:2011/05/22(日) 18:31:22.40 ID:???
いい例えがあります。
0でも1でもないNULLの扱いについて
「ガソリンが空の自動車と、ガソリンを入れる場所が無い自動車は違う」
751NAME IS NULL:2011/05/22(日) 18:33:33.82 ID:???
そろそろ次の問題に行こうよ。
752NAME IS NULL:2011/05/23(月) 00:32:40.01 ID:???
>>749
おまえは本当に詭弁ばかりだな。
753NAME IS NULL:2011/05/23(月) 00:40:14.27 ID:???
それはブレーキじゃないって、じゃあなんだよ。
事故りそうになったら勝手に止まったり、自動回避するのが
おまえのいうブレーキなのか?日本語しゃべれ
754NAME IS NULL:2011/05/23(月) 01:14:58.51 ID:???
じゃあ、なにがどうブレーキになるのか説明してみな。
755NAME IS NULL:2011/05/23(月) 09:55:27.57 ID:???
俺の言い方のほうが正しい
っていう話ならどっかよそでやってくれんかな
756NAME IS NULL:2011/05/26(木) 22:43:04.01 ID:OPfQB748
アクセスが失敗した場合にエラーメッセージを記憶する方法として

[アクセステーブル]
アクセスID PK NN AUTOINCREMENT
アクセス時 TIMESTAMP DEFAULT CURRENT_TIMESTAMP
エラーメッセージ TEXT

とするか

[アクセステーブル]
アクセスID PK NN AUTOINCREMENT
アクセス時 TIMESTAMP DEFAULT CURRENT_TIMESTAMP
エラーあったか? BOOLEAN

[エラーテーブル]
アクセスID PK FK NN
エラーメッセージ TEXT

とするのはどちらがいいのでしょうか?
頻繁に失敗するようなものじゃないので
BOOLEANのほうがいいのかな?なんて思ってこうしました
エラーあったか?どうかのフラグ自体いらないでしょうか?
757NAME IS NULL:2011/05/26(木) 22:51:59.40 ID:???
いらん。
758NAME IS NULL:2011/05/26(木) 23:33:21.45 ID:???
>>756
真ん中の案は、エラーの有無が分かるのみで内容が分からない。
下の案は、エラーの内容はメッセージで分かるのだろうが、日時が分からない。

単純に情報量の観点から、上の案がよいのでは?

はい。次の問題お願い。
759NAME IS NULL:2011/05/26(木) 23:44:03.22 ID:???
テーブルを1つにするか、2つに分けるか
聞いてるんじゃないの?
下の案でもいいけど、フラグはいらんな
760NAME IS NULL:2011/05/26(木) 23:45:51.47 ID:???
>>756
それだけだと上側を使って、エラーなしの時はエラーメッセージを空にしておけば十分だと思う。

あと、下側のだけど、エラーあったかフラグは論理設計としては要らない(エラーテーブルを見ればわかるので)。
実装でも、(エラーテーブルの参照がボトルネックになるとか)よっぽどじゃない限り要らない。多分、ビューで十分。

論理設計としては、エラーに付随するデータが他にもあったり、追加される可能性が高いなら分割しておくと分かりやすい。
ただ、実装の場合、分割すると使い辛くなるので、1つのテーブルにまとめることも多い。
どこまで論理設計に近い形で実装するかは人によって優先順位が違うので、性能要件を満たす範囲で自分で決めて。
761NAME IS NULL:2011/05/27(金) 00:15:48.42 ID:???
エラーなしなら、そもそも登録しなきゃいい。
762756:2011/05/27(金) 00:24:51.67 ID:???
みなさんどうもアドバイスありがとうございます
みなさんの意見を総合的に判断して
一番上の案でいこうと思います
763NAME IS NULL:2011/05/27(金) 00:48:15.02 ID:???
create table a (
aa int primary key not null
);

create table b (
bb int primary key not null
);

create table c (
aa int foreign key references a(aa),
bb int foreign key references b(bb),
primary key(aa, bb)
);

create table d (
aa int foreign key references c(aa),
bb int foreign key references c(bb)
);

この時dのaaが参照してるのは結局aのaaということになるんでしょうか?
764763:2011/05/27(金) 02:20:16.39 ID:???
なんか色々勘違いしてました。
リファレンスってかいてたので、
親の値(aのaa)が変わったら子の値(cとdのaa)も変わると思ったら、
そういうもんじゃないみたいですね。
765NAME IS NULL:2011/05/27(金) 02:54:08.66 ID:???
ON UPDATE を指定すれば、そういうこともできるけどね。
あと、スレ違いだよ。そういう質問は質問スレに行ったほうが良いよ。
766763:2011/05/27(金) 15:12:36.81 ID:???
ありがとうございます。
そちらのスレで質問かえてきいてみます。
767NAME IS NULL:2011/05/31(火) 20:01:26.37 ID:???
他のテーブルで同じ列を扱う場合
名前は一緒にすべきですか?
そのへんのサイト見ると別の名前にしてたりするようですが・・・

CREATE TABLE foo ( foo_id INT(5) NOT NULL, PRIMARY KEY (foo_id) );
CREATE TABLE bar ( bar_id INT(5) NOT NULL, foo_id INT(5) NOT NULL, PRIMARY KEY (bar_id) ) ;
768NAME IS NULL:2011/05/31(火) 21:30:38.67 ID:???
>>767
設計とペアで考える事柄です。
その2つのテーブルは関連性があるから同名の列項目があるんですよね?
たとえばmemberとmember_detailとか。

テーブル通しが親子関係なものであることを想像します。
(非常に関係が深い)

反対に同内容で別列名があるなら、子の関係にあるものが、
親とは違うタイプのどれかのテーブルの”親”である事を想像します。
(親と孫との関連性が低い)

どうでしょうか。
769767:2011/05/31(火) 22:03:03.87 ID:???
>>768
おっしゃるとおり関連性があるから同名の列項目があります
ただ外部キーとしてるわけでないので関連性があると言っていいのかよくわかりませんが
関連性を高めるために外部キーにすべきでしょうか?
770NAME IS NULL:2011/05/31(火) 22:03:19.54 ID:???
>>767
自由。

個人的には、カラム名は、テーブルに
対して定義するものだと認識している。
つまり、他のテーブルと同じカラム名に
なるかどうかは、テーブルとカラムの
役所による。
771NAME IS NULL:2011/05/31(火) 23:22:53.11 ID:???
>>767
ここで「他のテーブルで同じ列」と言っているのはfoo.foo_idとbar.foo_idのこと?
それらの定義域が同じ(bar.foo_id=1はfoo.foo_id=1と同じ値を意味している)ならば
同じ名前を使うのが自然だと思うが。
772NAME IS NULL:2011/06/01(水) 01:44:37.73 ID:???
リバース出来るツールで名前解釈しかないのとかもあるしね
773NAME IS NULL:2011/06/01(水) 13:39:05.65 ID:???
同じものを表してるのに
名前が違うのは不自然だろ
774NAME IS NULL:2011/06/01(水) 14:29:33.81 ID:???
joinの結合条件にusingってのがあるが、
あれは、同じ項目名であることが前提
つまり結合に使うような同じ項目は同じ項目名にしておけってことかと

それ以外で同じ項目が違うテーブルに複数存在するのは設計的におかしいので
違う名前を付けるべき
775NAME IS NULL:2011/06/01(水) 21:30:49.99 ID:NvcrXtYy
>>767
「関連性がある」だけではなく、具体例を挙げてください。

例えば・・・

受注:(*受注番号、受注件名)
受注明細:(*受注番号、*連番、商品コード、数量、単価)
商品:(*商品コード、単価)

上記の場合、
受注と受注明細における「受注番号」は、当然同じ名前にすべきだと思う。

但し、
受注明細と商品における「単価」は、同じでもよいし、違っててもよい。
なぜなら、商品の単価は、現時点の単価であり、
受注明細の単価は受注時点の単価だから。

この単価の例の場合、
個人的には、列名は同じだとしても、せめて日本語名は(区別する意味で)違ってて欲しいと思ってる。
(受注時単価とするなど)

できるだけ他人に仕様を勘違いさせない・・・
という観点も、命名の上では大事だと思う。
776NAME IS NULL:2011/06/01(水) 23:26:18.96 ID:???
hoge.id、FKでhoge_idとかついやってまう・・・
hoge.hoge_idはなんか冗長な感じがして
777NAME IS NULL:2011/06/02(木) 12:13:35.24 ID:???
まぁ、どっちでも良いが、最初に決めたルールは守ってくれ。
778NAME IS NULL:2011/06/02(木) 16:15:23.27 ID:???
>>775
DB設計は初心者です。質問です。
受注明細に*連番とありますが、なぜこの項目が
入っているのですか?
779NAME IS NULL:2011/06/02(木) 20:22:15.18 ID:???
なかったら、明細行が特定できないじゃん。
780NAME IS NULL:2011/06/02(木) 21:00:14.11 ID:???
>>778
DB構造=帳票レイアウトにしたいからじゃないの。
781NAME IS NULL:2011/06/02(木) 21:00:48.33 ID:3Fmc6QwL
>>779
「商品コードで特定すればいいじゃないか?」・・・というのが、>>778の言いたいことだと思います。

>>778
>>775はあくまで例です。

実際のところ、「同一受注番号内に同一商品コードを持つ明細は複数存在しない」
・・・という前提があればご指摘のとおり、連番は不要でしょう。

・・・が、この前提を覆す状況はいろいろと考えられると思います。

例えば、
受注は明細単位で取消可能とする。
受注明細の取消は「数量にマイナスの数値を入れて登録することで管理する」
・・・という(少し無茶な)要求があったとしたら?

例えば、
同一の商品を10個受注した際に、「3個はA社、7個はB社から仕入れて販売します」
・・・という状況が業務上ありえるとして、それが事前に(受注登録時点で)分かっている場合は、
明細を分けて登録する運用としたい…という(これまた少し無茶な)要求があったら?

つまり、
「連番は無いのが正解」・・・ではなく
「いや連番はあったほうがよい」・・・でもなく
>>775にある情報だけでは、一概に決められない」が正解だと思います。
782NAME IS NULL:2011/06/04(土) 10:06:54.62 ID:???
>>776
RDBMSにおけるテーブルとカラムは、1:n関係ではなくn:m関係であると
激しく主張したい。
783NAME IS NULL:2011/06/04(土) 10:20:24.17 ID:???
>>776の意味をどなたか解説して下さい
784 忍法帖【Lv=3,xxxP】 :2011/06/04(土) 10:26:58.90 ID:???
>>783
foo . id、bar . idと2つのテーブルにそれぞれidがあり、互いに関連性(例:親子関係)があるとき、
bar には bar . foo_idという列があるが、SQLを書くときは WHERE foo . id = bar . foo_idとなる。

同じものを表しているのに、名前が異なるので混乱する可能性が高い。

ただし、実際のOSSでもたまに見るので、上記の書き方で違和感が無いなら別にいいのでは?
785NAME IS NULL:2011/06/04(土) 12:48:30.01 ID:???
>>783
CREATE TABLE User (id INT, PRIMARY KEY (id));
CREATE TABLE Profile (user_id INT, FOREIGN KEY (user_id) REFERENCES User(id));

恐らくこういう事かな?
RoRのActiveRecordがこの命名規則だったはず
俺は合理的で好きかも知れん
786NAME IS NULL:2011/06/04(土) 16:37:09.08 ID:???
ORマッパーだとよくある規則だな。>hoge_id
SQL自動生成時に都合がいいらしい。

ただいかにも「ORMを使うために決めたDB構造」で
俺は好きじゃないが。
787NAME IS NULL:2011/06/04(土) 18:46:24.83 ID:???
もともとのRDBの考え方では、テーブルX(A,B)というのはAとBの間に何らかの
関係があるときにそれをXと表すということであって、「XのA」じゃないんだな。
それはエンティティやオブジェクトとしての考え方であって。
だから前者の考え方に立てば、X.idとY.idが同じものを表していないならば同じ名前を
付けるべきではない。
優劣をつけるつもりはないけど、どっちの考え方でいくかは意識しておいたほうがいい。
788NAME IS NULL:2011/06/04(土) 19:43:45.21 ID:???
>>787
表は集合の境界ですか。目から鱗
その考え方ならば foo_id だけじゃなく他の属性も foo_name, foo_time
の様にしないと命名に一貫性がないような…
789NAME IS NULL:2011/06/04(土) 20:45:07.71 ID:???
リレーショナルモデルではそう。foo_nameとbar_nameが別のnameを表すなら
そのようにしておくべき。逆にnameという属性がスキーマ内で唯一のものであれば
nameのままでもかまわんけど。
790NAME IS NULL:2011/06/05(日) 01:40:04.51 ID:???
実際のとこ
nameとかだとちゃんと区別できるように別の名前にするんだが
IDとかそのままの場合が多いよね
791NAME IS NULL:2011/06/05(日) 16:07:12.99 ID:???
>>789
nameだって変域に付けた呼び名だから、同一概念を指すなら共通にするべき。
792NAME IS NULL:2011/06/05(日) 16:46:36.87 ID:???
この場合の「同一概念」ってのはどういう意味?
793NAME IS NULL:2011/06/05(日) 17:11:38.65 ID:???
すべてのものに名札が貼ってあってその名札をnameと呼ぶ、みたいな。
794NAME IS NULL:2011/06/05(日) 17:27:02.38 ID:???
氏「名」も市町村「名」も同一概念ってことか。
いわゆる森羅万象テーブルを作るならそうなるな。
795791:2011/06/05(日) 17:41:07.20 ID:???
>>794
そういうことになる。
四季{春,夏,秋,冬} が対象となるフィールドがあって、
このテーブルではもっぱら春と秋しか使わないに違いないから、
四季という名を使いませんというのもおかしいのではないか。
796NAME IS NULL:2011/06/05(日) 17:59:06.75 ID:8V28U8iF
検索する予定がないカラムに複数の項目をカンマで区切って入れてもいいんでしょうか

ID 名前  年齢  好きな食べ物
001 山田太郎 13 いちご,みかん,りんご
797NAME IS NULL:2011/06/05(日) 18:04:31.03 ID:???
ここでテーブルは関係ないな。
それはそれとして、つまり四季のフィールドも二十四節気のフィールドも
「季節」という同一概念だから同じ名前にすべきだってことだろ?
798NAME IS NULL:2011/06/05(日) 18:23:21.63 ID:???
>>796
その項目でなにか処理しないんならいいんじゃね。
799NAME IS NULL:2011/06/05(日) 20:10:22.18 ID:???
>>796
カラムは最小単位で作るのが基本

>>798
なにも処理しないならそもそも保存する必要すらないっていう
800NAME IS NULL:2011/06/05(日) 20:16:56.79 ID:???
「最小単位」の捉え方しだいだな。
単にカンマが含まれたテキストとして扱うならば>>796のままでもかまわんし。
801NAME IS NULL:2011/06/05(日) 21:16:53.01 ID:???
>>799,800
DBの処理はなにもしないんですが、そのテキストの言葉を利用して
phpで処理する場合カンマ区切りだと都合がいいのでそうしてるんですが、
使い方まちがってませんか?
802NAME IS NULL:2011/06/05(日) 21:18:28.34 ID:???
別に間違ってないよ。
803NAME IS NULL:2011/06/05(日) 21:41:43.79 ID:???
>>799
>なにも処理しないならそもそも保存する必要すらないっていう

単に表示するだけのフィールドとかあるでしょ。

このスレだから、わざさわざ「(SQL で) 処理しない」って書かなくても
理解できると思ったが...。
804NAME IS NULL:2011/06/05(日) 22:32:34.18 ID:???
>>800
>>796はきっぱり「複数の項目をカンマで区切って」って書いてあるから
最小単位でカンマ区切りテキストが入ってるとは考えにくいと思うが

>>801,803
それは本来DB(SQL)でやるべき作業をアプリにやらせてる可能性が高いぞ

まあどこまでがDBでどこまでがアプリでやるべき作業かってのも
考え方によって変わるだろうし、やってみて不都合なければいいとも言えるが
805NAME IS NULL:2011/06/06(月) 10:03:17.41 ID:???
>>804
カンマ区切りのほうが配列に一発で入るので便利かなと・・・。
それか普通に別のテーブルを用意するほうがいいのか迷っていたのです。
806NAME IS NULL:2011/06/06(月) 13:16:17.21 ID:???
CSVならタブ区切りを使うな
807NAME IS NULL:2011/06/06(月) 13:17:07.80 ID:???
カンマだと色々弊害が起きる
808NAME IS NULL:2011/06/06(月) 14:01:19.10 ID:???
>>806
お前他スレでもTSV言ってたろw
CSVに親でも殺されたのか?
809NAME IS NULL:2011/06/06(月) 14:05:06.19 ID:???
>>805
つまり

DBに格納する前に、配列の各要素を結合する
DBから取り出した後に、分解して配列の各要素に格納する
という処理を毎回行う

各要素に対する処理はアプリケーションで行う

これに疑問を感じない、そのほうが便利だって思うならそうすれば良いと思うよ
810NAME IS NULL:2011/06/06(月) 14:15:29.72 ID:???
>>808
CSVならタブが良いと書き込んだだけで
人違いされたあげく親まで殺されるのか
キチガイにも程がある
811NAME IS NULL:2011/06/06(月) 15:00:42.94 ID:???
>>809
疑問を感じたから質問したんじゃないの?
そのまわりくどい言い回しは何
ベストな方法を書いてやれよw
812NAME IS NULL:2011/06/06(月) 18:44:20.51 ID:???
>>809
splitとかjoinとかで一撃な言語の方が多くね?
DBでもっと楽な解決できるのかいな
813NAME IS NULL:2011/06/06(月) 19:49:07.68 ID:???
カンマ(タブ)エスケープはどうすんだとか、要素を検索しろとか要素でJOINしろとか
ちゃんと検討しての発言とは思えないな。
814NAME IS NULL:2011/06/06(月) 20:16:38.55 ID:???
>>812
よく使うけどDB使う時にわざわざやらないなあ。
ちょっとしたバッチやアプリでは便利。
815NAME IS NULL:2011/06/06(月) 22:40:51.60 ID:QJwN+Qol
>>796

ID 名前  年齢  好きな食べ物
001 山田太郎 13 いちご,みかん,りんご

この例で、
「いちご、みかん、りんご」は表示するだけの情報であるならば、
カンマ区切りのテキストのままDBに格納しておくことで事足りるかもしれませんが、
この手法に違和感を感じるのも事実です。

加えて、表示するのみの情報であっても、
並び順を変えたいとか、言葉を変えたいとか、
好きな食べ物に関するデータの統計を取りたいとか、
いろいろな要望が今後出てくる可能性もあります。

ですので、保守性を考えて、やっぱり情報は分割すべきかと思います。

以下は例ですが、

食べ物をマスタ化しないなら、
-------------------------------------------
社員(*社員ID、名前、年齢)
好きな食べ物(*社員ID、*連番、食べ物名)
-------------------------------------------

食べ物をマスタ化するなら、
-------------------------------------------
社員(*社員ID、名前、年齢)
好きな食べ物(*社員ID、*食べ物コード)
食べ物(*食べ物コード、食べ物名)
-------------------------------------------

食べ物をマスタ化し、食べ物コードに変更を加えることなく、食べ物の並び順の変更に耐えうる形なら、
-------------------------------------------
社員(*社員ID、名前、年齢)
好きな食べ物(*社員ID、*食べ物コード)
食べ物(*食べ物コード、食べ物名、並び順)
-------------------------------------------

・・・などなど、いろいろ思いつきますが。

余談ですが・・・
「社員」に「年齢」という項目は、違和感がありますね。
毎年1回の基準日に全社員を対象に(?)
あるいは毎日その日が誕生日である社員を対象に(?)
インクリメントする必要がでてきてしまいます。
「年齢」ではなく「生年月日」がいいですね。本当に余談ですが・・・。
816NAME IS NULL:2011/06/06(月) 23:21:53.33 ID:???
使われてない・使うかどうか分からないテーブルがあるほうが保守性が悪いよ。
今回のケースならテーブルを分けるのは、それが必要になることが分かった時点で充分だろう。
817NAME IS NULL:2011/06/06(月) 23:33:43.20 ID:???
あいかわらず、予断で語る奴が多いなぁw
818NAME IS NULL:2011/06/07(火) 03:54:45.17 ID:RztXzyzH
素人の素朴な疑問でここで聞いていいのかもよくわからないのですが、お願いします

サイトAで使われてるデータベースとその情報があり、
それとは別にサイトBで使われているデータベースとその情報があるとします。
で、新規にサイトCを作って、そこでAとB両方のデータベースの情報を取り扱うとき、
A,B,Cのデータベースはどういうふうに作ったら効率的なんでしょうか?

AもBもそれぞれ、webサーバ+DBサーバを一つのハードの中で動かしてる場合、
Cから同じ検索クエリをA,Bに送って帰って来た結果を表示することになると思うんですが
もっと賢いやり方はないのかなと。

たとえばヤフーで賃貸物件検索するのに、atHomeとかCHINTAIとか複数の
物件紹介サービスの情報を一括で抽出できると思うんですが、ああいうのはどうやってるんでしょうか?
両サービスのDBから定期的にヤフーのDBにバックアップを落として来てソコで検索してるとしたら
古い情報を検索することになりかねないし、リアルタイムで各サービスに問い合わせるとしたら
自前のDBに問い合わせるよりも遅くなったり「東京」を示すパラメータを各サービスのそれに
整形する手間などがかかりそうだし、一つのサービスが落ちてたときの処理が面倒そうだし…

ヤフーからの検索対象DBを専用に作って、各サービスはそこで(リアルタイムに?)
レプリケーションという奴をやっていて、ヤフーはそこを検索してるんでしょうか?
また、こういう複数のサービスでデータの乗り入れ?をする場合、DBサーバは
専用/共通のハードの中で動かした方が速いものなんでしょうか?
Mysql5を想定しています
819NAME IS NULL:2011/06/07(火) 05:02:14.34 ID:???
リモートのデータベースに直接つなげるならそれでなにか問題が?と思うが。
ネットワーク的に遠いなら検索用DBを作るのはやってるだろう。

賃貸物件は例えが悪いな。
こんなもん1日何十回も更新するもんでもないだろうから定期的に情報を取得する仕掛けを作ればいいだけ。
820NAME IS NULL:2011/06/07(火) 06:11:05.64 ID:???
あーゆーのは、Webサービス公開してて、Yahooはそれ呼んでるだけじゃないの?
821NAME IS NULL:2011/06/07(火) 06:40:47.37 ID:???
>>805
各項目を固定長で入れておいて、viewで処理する手はある。
固定長に整形するアプリケーション側にコストがかかるが。
822NAME IS NULL:2011/06/07(火) 09:38:35.57 ID:???
>>815
詳しい説明ありがとうございます。
年齢は生年月日にしてあとから計算するほうがよさそうです。

食べ物名の形式はとくにないので
例えば、いちごの場合はカタカナのイチゴかもしれないし半角のイチゴかもしれないし漢字の苺かもしれないし
イチゴ味のアイスかもしれないんので、
とんでもないことになりそうなんです。
823NAME IS NULL:2011/06/07(火) 21:59:25.28 ID:???
>>822
であれば、>>815で提案した案のうち、
マスタ化する方法を取ればよいのではないでしょうか。
824NAME IS NULL:2011/06/08(水) 01:10:46.04 ID:???
テーブル設計的には>>815のような感じで分けた方が良いけど、
プログラミング的には>>796の方が圧倒的に楽だよ(年齢は駄目だが)
SQLは簡単だし、抽出も早いし。

堅く作る必要が無いなら>>796の方で十分でしょ。
マスタ化した方が綺麗だけど、面倒この上ない。

ただ、自分ならセパレータはカンマじゃなく、コロンとかセミコロンとか"|"とかにするけどね。
カンマだとcsv化したくなった時に厄介。
825NAME IS NULL:2011/06/08(水) 01:50:20.09 ID:???
>>824
お前は何を言ってるんだ。
826 忍法帖【Lv=3,xxxP】 :2011/06/08(水) 07:16:25.22 ID:???
!ninja
827NAME IS NULL:2011/06/08(水) 09:45:25.14 ID:???
>>796
つ GROUP_CONCAT()
設定による長さ制限があるけど、使える
場合には悪くない。

>>824
セパレータを選べるならタブだろ。
CSVの心配だけしてもしかたない。
828NAME IS NULL:2011/06/08(水) 15:16:25.49 ID:???
>>827
長さ制限以前に、使えるDBMSに制限があるわけだが

セパレータを選べるなら、データに含まれる文字を吟味してから決定するがな、俺なら
まあ、セパレータどうするかはスレ違いだからよそでやってくれ
DB設計で考えれば、セパレータを含む項目があるのがまずおかしくないか考えんとな
829NAME IS NULL:2011/06/09(木) 04:03:50.72 ID:???
明らかにダメなテーブル設計があり、
それが原因でプログラムがグチャグチャになっています

出来ればテーブル設計を一からやり直したいのですが
そのテーブルを既に使って運用しているシステムがいくつもあります
全てを作り直すのは現実的ではないようです

プログラムコードのリファクタリングのように、データベースのリファクタリング?を段階的に行えれば少しずつマシな状況に出来るのではないか?と思うのですが、
こういった用途に有効な手法はあるでしょあか?
書籍などへの誘導でも有難いです
830829:2011/06/09(木) 04:18:23.47 ID:???
(続きです)
具体的には
・特定のカラム(たち)に格納されたコード値によって、その他のカラムたちに格納されている値の意味が変わるテーブル
・特定のカラム(たち)に格納されたコード値によって、結合するテーブルが変わるテーブル構成
・COL1, COL2, …,COL50のような、テーブル定義だけでは用途が不明なカラム名が使われたテーブル(別途説明の仕様書はあり)
・業務用語と対応しない英語名称でカラム名がつけられており、本来対応すると思われる英語名称のカラムは全く別の用途でつかわれているテーブル(理解の妨げや誤解やバグが発生しやすい)

など凄惨とした状況です。
831 忍法帖【Lv=16,xxxPT】 :2011/06/09(木) 06:54:48.64 ID:???
無理。
832NAME IS NULL:2011/06/09(木) 07:44:02.97 ID:???
ビュー使え
833NAME IS NULL:2011/06/09(木) 08:01:23.26 ID:???
>>825
恐らくいちご,みかん,りんごがエンティティになることはないのでしょう。
集計したいときは・・・名寄せだな
834NAME IS NULL:2011/06/09(木) 08:24:13.13 ID:???
>>830
ビューとストアド使って整理。
それで問題がないようなら、改修を提案。
既存のデータがあるから改修出来ない何て言うのは甘え。
835NAME IS NULL:2011/06/09(木) 10:40:22.95 ID:???
>>829
>834の言う通り。改修できないは甘え。
今直さないでいつ直す?被害が拡大するだけ。
書籍なら、データベース・リファクタリング
ttp://www.amazon.co.jp/dp/4894715007
836NAME IS NULL:2011/06/09(木) 15:56:22.71 ID:???
>>834
既存のデータが問題なんじゃなくて、既存のプログラムが問題なんだろ
甘えじゃなくて、現実的なコストの問題だよ

やるなら一気にやらないと
段階的にやると各段階で修正、テストが必要になって工数が増えるだけだぞ
837NAME IS NULL:2011/06/09(木) 16:04:00.13 ID:???
>>836
どう読んでもデータ構造の問題だろ。
838NAME IS NULL:2011/06/09(木) 16:22:49.66 ID:???
うむ
839NAME IS NULL:2011/06/09(木) 16:32:31.82 ID:???
複数システムが参照してるDBを一気に差し替えは現実的じゃないよ
よほど体力あって問題認識してる企業なら別だが普通はNOって言われる

関連システムでデータアクセス周りが共通化されてたりしたらある程度コスト減らせるけど・・・
840NAME IS NULL:2011/06/09(木) 17:00:35.38 ID:???
最前線のDB設計を書いた本って何がおすすめなのん?
841NAME IS NULL:2011/06/09(木) 18:12:00.86 ID:???
>>837
データ構造に問題があるのはわかってて、そのデータ構造を修正するならばって話だぞ
既存データがあるから修正しにくいってことはあまりないが
既存プログラムの修正には工数がかかるってことだ

>>839
まあ、現実的にはかなり厳しいだろうな
で結局はそのまま放置されて>>829のような状態に
842 忍法帖【Lv=7,xxxP】 :2011/06/09(木) 21:01:22.03 ID:???
>>840
会社の先輩に聞くか、有料の顧客サポートで聞いた方がいい。
843NAME IS NULL:2011/06/10(金) 00:25:40.61 ID:???
>>841
>既存プログラムの修正には工数がかかるってことだ

そんな当たり前の話をドヤ顔で書かれてもw
844NAME IS NULL:2011/06/10(金) 03:54:18.65 ID:???
トランザクションは銀行システムで使うとかいう説明がよくありますが、
最近のシステムはなんでもトランザクション処理してもいいですよね?
845NAME IS NULL:2011/06/10(金) 04:50:04.87 ID:???
UNIQUEをつけたカラムがインデックスと教わったのですが、
遅くなるからインデックスをあまり造り過ぎない=UNIQUEカラムをあまり作らない
だと思ってたのですが、なんかインデックスについて調べてるうちにどうも違うような・・・?
846 忍法帖【Lv=22,xxxPT】 :2011/06/10(金) 06:31:12.48 ID:???
違うね。
847NAME IS NULL:2011/06/10(金) 07:09:37.54 ID:???
>>844
自分の記憶では銀行といえばオンラインシステムの説明だったが…
848 忍法帖【Lv=22,xxxPT】 :2011/06/10(金) 07:17:00.95 ID:???
アプリ設計の話で、DB設計とは関係ないな。
849 忍法帖【Lv=7,xxxP】 :2011/06/10(金) 12:22:15.06 ID:???
>>844
要件による。
INSERT・UPDATEで即COMMITもあるし、
100レコード単位でのCOMMITもある。

トランザクションの説明として銀行の入金・出金が使われるだけで、
概念さえ分かれば銀行の話は忘れていい。
850NAME IS NULL:2011/06/11(土) 00:24:53.36 ID:???
>>830
ビューやストアドを使って、
うまく整理するしかないですね。

ただ、データを整理すること、設計を正すことに対し、
理解が得られないような現場の場合、
ビューを使うこと自体、理解が得られない可能性が高いですけどね。

そういうデータベースに対しては、小手先のテクニックで
うまく付き合っていくいかないかもしれないですね。

>・特定のカラム(たち)に格納されたコード値によって、結合するテーブルが変わるテーブル構成

これについては、情報処理技術者試験(DBスペシャリスト)が午後Uの問題で好んで出題する
「スーパータイプとサブタイプ」の考え方であるならば、
あながち、おかしい設計ではないと思いますけどね。
(たち)っていうのが、気になりますが。

>・COL1, COL2, …,COL50のような、テーブル定義だけでは用途が不明なカラム名が使われたテーブル(別途説明の仕様書はあり)

これも仕様書があるなら、「何とか頑張る」しかないと思います。

>・特定のカラム(たち)に格納されたコード値によって、その他のカラムたちに格納されている値の意味が変わるテーブル

これもCASE〜WHENやCOALESCEをうまく使って頑張る。

>・業務用語と対応しない英語名称でカラム名がつけられており、本来対応すると思われる英語名称のカラムは全く別の用途でつかわれているテーブル(理解の妨げや誤解やバグが発生しやすい)

名称はカラムを識別する記号であって、そこに意味を求めない
・・・と割り切って頑張る。
851NAME IS NULL:2011/06/11(土) 08:01:13.69 ID:???
>>845
> UNIQUEをつけたカラムがインデックスと教わったのですが、

誰に教わったか知らないけど、 UNIQUE と INDEX は全然別物。
UNIQUE でないフィールドに INDEX をつけることも可能。
ただ UNIQUE 指定されたフィールドを持つテーブルに挿入/変更しようとしたら
インサートしようとしている値がないか調べる (=検索する) 必要があるから
INDEX 作っとかないと遅くてしょうがない。

>遅くなるからインデックスをあまり造り過ぎない=UNIQUEカラムをあまり作らない

INDEX って、挿入/更新時の性能をちょっと犠牲にして検索を高速化する指定だけど
理解できてる?
852NAME IS NULL:2011/06/12(日) 09:32:16.39 ID:???
>遅くなるからインデックスをあまり造り過ぎない=UNIQUEカラムをあまり作らない

必要なら作るし不必要なら作らない……当たり前
853NAME IS NULL:2011/06/12(日) 23:49:32.92 ID:???
>UNIQUEカラムをあまり作らない

全然理解出来ない。後から考えるものなのか?
854NAME IS NULL:2011/06/13(月) 06:36:46.71 ID:???
インデックスを作るのは
プログラマの仕事っていう現場があったな。
855NAME IS NULL:2011/06/13(月) 07:00:53.92 ID:???
>>854
プログラマとマネージャしかいなんだろ
856NAME IS NULL:2011/06/13(月) 08:01:22.12 ID:???
SEもプログラマと同じようなレベルの
現場だったけどな
857NAME IS NULL:2011/06/13(月) 08:18:06.82 ID:???
SEなんて言葉使ってるとこがまともな役割な訳ないわな
858NAME IS NULL:2011/06/13(月) 08:37:29.20 ID:???
プログラマが昇格しただけだかんな
何もできん奴もいるしな
859NAME IS NULL:2011/06/13(月) 09:12:44.99 ID:???
>>856
そういう企業はSEと社長しかいないな
新人でも外向けの工数資料じゃ立派なSEさ
860NAME IS NULL:2011/06/13(月) 11:22:30.59 ID:???
コードを書いた事のないSEもいる訳ですが
861NAME IS NULL:2011/06/13(月) 11:40:19.18 ID:???
SQL質疑応答スレ 11問目から来ました。よろしくお願い致します。

現在商品サイトをつくろうとしてる新参でございます。
MYSQL+perlにて、商品データベースを構築し、順次カテゴリ別に商品を表示し、また別個に商品ページを生成する
CGIまではなんとか形にすることが出来ました。
次のステップとしてサイト内検索を行いたいと思っているのですが、
その場合、商品データベースとは別にデータベースを構築し、サイトのHTMLなりからタグをはずした
文字データ、検索ID、リンク先を各カラムとしたテーブルをつくろうと考えております。

検索データベース

検索テーブル

検索ID | 文字データ | リンク

検索文字を文字データと付きあわせてヒットしたらリンク先を返すという方法で検索したいのですが、
実際、こういう風に検索するやりかたは妥当なのでしょうか?他にもっと良いやり方はありますでしょうか?
よろしくお願い致します。
862NAME IS NULL:2011/06/13(月) 12:42:06.78 ID:???
Googleのサイト内検索じゃダメなの?
863NAME IS NULL:2011/06/13(月) 18:58:42.77 ID:???
>>861
商品名や商品説明で検索したいの?
それともperlから出力されたHTMLからフルで検索したいの?

もし後者だとしたらDBでやらない方が一般的じゃないか。
HTMLテキストを形態素解析とかで単語ごとに分割してキーワードファイル出力&ソート&ページ位置も保持
みたいな感じじゃね
864NAME IS NULL:2011/06/13(月) 19:59:30.64 ID:???
>>861
検索テーブル作るとして、その検索テーブルのメンテナンスどうする気だ?
サイト内検索で検索する対象をあらかじめ登録しておきたいとかなら良いんじゃね
キーワード検索みたいなイメージかな

単純にサイト全文検索したいってなら違う方法考えた方がいいかも
865861 ◆HdGP67B7KA :2011/06/13(月) 20:09:38.55 ID:???
>>862
そうですね・・・プログラミング言語の理解を深めることも二次的な目的となっていますので、
できるだけツールを頼らずに実現したいのが本音です
>>863
両方実現できたらなと思っています。
商品名や、商品名検索はカテゴリ別でソートするCGIの製作過程の副産物で実現できると考えております。
ただ、今回実現したいのはサイト内検索でして、CGIで吐きでたHTMLはリクエストによって順次変わってしまうため検索対象外、
または共通部分だけデータベースにテキストとして保存しておいて検索文字にヒットしたら
そのCGIのリンク先を返すという感じにできたらと思っております。
たとえば、データベースで実現しない場合、ながれとしては、

  ●検索文字送信 → ●検索CGI・・・・・・・・・【マッチの有無】・・マッチした → ●HTML(検索結果ソート)生成
                  ↓↑             ・
      キーワードファイル読込(text or dat)      ・
                              マッチしない
                                 ↓
                            ●HTML(検索結果無し)生成

でしょうか。
もしこうするなら、キーワードファイルにリンク先と位置(#id名)、たとえばキーワードファイルの中身としては

トマト,http://www.nanashi.com/product/html#tomato
レモン,http://www.nanashi.com/product/html#lemon
キャベツ,http://www.nanashi.com/product/html#cabbage



こういう感じでしょうか。
866861 ◆HdGP67B7KA :2011/06/13(月) 20:18:14.92 ID:???
>>864
今現在実現したいのは後者ですね・・・
もし、データベースを使わないで実現できる方法でベストな方法とはどういったものが考えられるでしょうか?
やはり、全ての単語を抜き出してひとつのテキストとし、それにリンク先が記述してあるという方法がベストでしょうか?
データベースを経由するだけ時間がかかってしまうということでしょうか
867NAME IS NULL:2011/06/13(月) 21:08:00.69 ID:???
全文検索, fulltext, 形態素解析, n-gram 等のキーワードで検索することをお勧めします。
868861 ◆HdGP67B7KA :2011/06/13(月) 22:18:18.30 ID:???
>>867
レスありがとうございます。
ひと通りググッて目を通してみました。
MYSQLにfulltextという機能があるのですね、勉強になります。
また、grep型やインデクス型など、インデクス型の形態素解析法、n-gram法いろいろ知れてよかったです。
自分がやろうとしていたことはfulltextで、おすすめいただいたのがインデクス型の形態素解析ということだったんですね
予め形態素解析なり、n-gramなりのエンジンをお借りしてインデクシングしたcsvテキストなりからヒットした文字を返す
という方法でしょうか。
つまり、一度インデクスス型でインデクシングして、それをgrep型で検索するという感じでしょうか。
インデクシングしたテーブルはデータベース化したほうが扱いやすいと思われますでしょうか。

869NAME IS NULL:2011/06/13(月) 22:57:42.63 ID:???
何かのパッケージソフトを使うならともかく、自力でやるなら DB に入れておいた方が扱いやすいと思うよ。
(キーワード, キーワードの抽出元) を保存しておいて、
検索はキーワードでクエリを投げる。抽出元が更新されたら、該当行を削除・再挿入で良いんじゃない。
870861 ◆HdGP67B7KA :2011/06/13(月) 23:21:26.99 ID:???
>>869
素早いご返答ありがとうございます。

やはりDBに入れておいたほうが良さそうですね(検索速度は落ちるかも知れませんが・・・)
メンテナンスは、抽出元が更新されたら自動でデータベース更新するCGIでも書こうと思っております(いつになるかわかりませんが・・・^^;)
とりあえず、インデクシングは形態素解析(Mecab)で、取扱いはデータベース(MYSQL)で行こうと思います。
いろいろアドバイスいただきありがとうとざいました。
871NAME IS NULL:2011/06/15(水) 02:49:56.90 ID:nPBjKqjs
タグ付けで複数タグを選択してデータ表示するような場合

社員テーブル(社員ID、名前)
免許テーブル(タグID、免許の名前)
社員タグ連結テーブル(社員ID、タグID)

または
社員テーブル(社員ID、名前)
免許テーブル(社員ID、免許の名前)

または
社員テーブル(社員ID、名前、免許の名前)
免許の名前にカンマ区切りで突っ込んで%LIKE%またはFULLTEXTINDEX

どれにしますか?
872NAME IS NULL:2011/06/15(水) 09:26:24.05 ID:???
それだけの情報じゃ何とも言えない。
データの件数は何件ぐらい?
求められる検索性能はどれぐらい?
免許に他の属性が追加される可能性が高い・低い・ない?
使用するデータベースやフレームワークは?

求められる要件・性能を満たす中で一番簡単に実装できるのにする。
873871:2011/06/15(水) 11:19:46.72 ID:nPBjKqjs
データベースは初心者です。自サイト用なんですが、
社員件数は5000件〜
免許タグ500程度
1社員につき、5〜15の免許
検索は早ければ早いほうが良い。
免許の属性は低頻度で追加・更新される
MySql+PHP5です。
874NAME IS NULL:2011/06/15(水) 13:23:35.53 ID:???
>>871
例えば、
・社員(社員ID, 社員名)
・免許(免許ID, 免許名, カテゴリ, 表示順序, 免許属性1, ...)
・社員免許(社員ID, 免許ID, 取得日, 失効日, 社員免許属性1, ...)
みたいに免許に属性があって、免許マスタの管理者がいるなら、一番上。

単に免許名だけを保存できれば良くて、ユーザーが自由に免許名を追加・削除するなら手軽さで真ん中。

一番下のは表示するだけなら良いけど、検索にも使う場合は他のコードと共通化し辛くて使いにくい。
875NAME IS NULL:2011/06/15(水) 18:30:57.21 ID:???
>>871
典型的な検索のパターンは?
免許をマスタ管理する、あるいはマスタ管理できないような要件が予想されうる?

1社員につき、5〜15の免許で社員件数は5000件だと、免許の総数は25000〜75000
それに対して免許タグは500程度しかない
まず免許のマスタ管理できるかどうか考えた方が良い


マスタ管理できるなら1番
名前でフル検索する必要があるなら2番
どっちにしても3番はない
876NAME IS NULL:2011/06/15(水) 19:55:54.50 ID:???
>検索は早ければ早いほうが良い。
ユーザーさんなら気持ちはわかるんだけど
技術屋さんならこれは言わないほうがいい。
877NAME IS NULL:2011/06/15(水) 22:53:51.23 ID:MWoOhBnR
>>871

これは>>796とほぼ同じ質問ですね。

上から@ABとすると、@がいいと思います。
というか、データベース設計的には(DB設計にスレですし)
@しか考えられないと思います。

AやBと比べて@の検索性能が低いとは思えません。
・社員テーブルと社員タグ連結テーブル
・免許テーブルと社員タグ連結テーブル
をそれぞれ結合することになりますが、
キー項目同士の結合ですので、性能が大きく下がることはありません。

たかだか、免許が数百件、社員が数千件、それらの連結が数万件という数に過ぎないわけですし。

また、免許の更新頻度は低いとのことなので、
マスタ管理も可能だと思います(というかすべきだと思います)ので、
AやBを選ぶメリットはほとんどないのではないでしょうか。
878NAME IS NULL:2011/06/15(水) 23:12:06.99 ID:???
1番目と2番目は実質変わらんだろ。サロゲートキーにするかしないかだけで。
879NAME IS NULL:2011/06/16(木) 04:12:40.83 ID:???
>>878
一つの免許を複数の社員に関連付けられるかどうかが違う
880NAME IS NULL:2011/06/16(木) 04:23:23.76 ID:???
>>871 でタグIDとかなってるけど免許IDだよなこれ
だとすると@ABの中じゃ@しかやはり有り得ないだろうな。

ABがありえる可能性としては、免許の名前が自由入力項目だったりする場合か。
自由入力でなく選択機能(場合によっては各種資格試験名とかも含んだり)をつくり込むと、
それだけで工数ばかりえらく掛かって実用性がなかったりとかで。
881NAME IS NULL:2011/06/16(木) 07:16:39.99 ID:???
>>879
テーブルの名前が違うけど1の社員タグ連結テーブルと2の免許テーブルが同等。
1でいう免許テーブルの有無だけの違い。
882NAME IS NULL:2011/06/16(木) 16:24:49.27 ID:???
>>881
1の社員タグ連結テーブルは、1件の免許タグ(=免許テーブルの1レコード)に対してn件の社員を持てる
2の免許テーブルは、1件のレコードについて1件の社員しかもてない

どこが同じだと?
883NAME IS NULL:2011/06/16(木) 19:09:55.20 ID:???
2の方法だと免許が管理できない。
同じ免許だけど名前がちょっと違う免許がいっぱい出来そう。

社員A データベーススペシャリスト
社員B DBスペシャリスト
社員C デスペ
884NAME IS NULL:2011/06/16(木) 21:56:19.36 ID:???
>>882
それは制約で決まることですね。2の免許テーブルにunique(社員ID)制約があれば
そうなりますが、(社員ID,免許の名前)であればそうはなりません。
主キーがどちらなのか、>>871に書かれていることだけでは判断できません。
仮に>>871の意図があなたの想像通りだったとしても。
加えて言えば、1も2も同じ制約を付けることができますし、同じ制約を付ければ
当然同じように振舞います。
885NAME IS NULL:2011/06/16(木) 23:53:04.20 ID:???
>>884
制約をどうすれば、2の免許テーブルの1レコードと複数の社員を関連づけれるんだ?
886NAME IS NULL:2011/06/17(金) 00:03:40.85 ID:???
なんか覚えたての難しい言葉を使いたがる年頃なんだろうなと思った ⇒ >>884

※ 個人の感想です。
887NAME IS NULL:2011/06/17(金) 00:05:03.81 ID:???
なんで1レコードでなきゃならんのだ。社員が複数いるんだったら複数入れりゃいいだろw
888NAME IS NULL:2011/06/17(金) 01:09:19.81 ID:???
>>887
同じ名称の免許を複数レコードつくって結びつけるならそれでいい

ただ、免許をマスタ管理するかどうかを考えたとき、マスタ管理するなら
一つの免許を複数の社員に結び付ける必要がある

その場合2番の方法ではダメだって言ってるんだが
1番と2番が同じだと言うやつがいてるんだ
889NAME IS NULL:2011/06/17(金) 07:05:09.49 ID:???
マスタ管理するならば1だってのはみんな言っている。マスタを用意してるのが
1の方だけなんだから当然だが。
同じ免許を複数の社員が持てないとか言ってんのはお前だけだ。
890871:2011/06/17(金) 07:12:42.97 ID:uAjYsTPJ
2のタグIDは免許IDのことです。
マスタ管理は一部以外出来ていません。

3が一番クエリ書きやすいと思ったのですが、
DBの良さを利用できるのが一番は1 次点で2ということでしょうか。
アドバイス有難うございます。

891NAME IS NULL:2011/06/17(金) 10:57:00.07 ID:???
>>890
免許に属性があるなら1
免許項目の検索が主目的なら1
作成するアプリで完結させるなら1

通信のデータ量/回数を抑えたい場合は3
登録検索だけ用意して集計などはデータを抜き出してExcelライクにするなら3
また、DB直接操作して一括にデータのやり取りをする場合も3が楽

当たり前だけどDB設計となると3は嫌われる。
でも実務的には結構有効。

…だと思うが、反論必死w
892NAME IS NULL:2011/06/17(金) 13:17:48.28 ID:???
>>891
3の記述が初心者には罠すぎるよw
893NAME IS NULL:2011/06/17(金) 20:23:42.63 ID:???
まあ次点とか無くて1の一択だよな。
2,3は社員テーブルに直接免許名を突っ込んでる次点で有り得ない。RDBを使う意味自体がない。
ただし、3は帳票作成時の中間テーブルとかなら有り得る。>>891の言ってるのもこれに近い。
894NAME IS NULL:2011/06/17(金) 21:14:27.23 ID:643a8dTu
DB設計のスレなので、
この手の質問には(特別な理由がない限り)、
@が正解という結論にならなければおかしいと思う。

特別な理由というのは、上で挙がっている
帳票作成時の中間テーブルとか、そういうケースのことですが。
895NAME IS NULL:2011/06/23(木) 16:46:44.76 ID:???
896NAME IS NULL:2011/06/24(金) 11:22:55.38 ID:WA8RBTIG
従業員をいろいろなグループに細分化してそれぞれに分担して作業をしています。
これらを管理するDBを作るとして、各グループにより必要なフィールドが異なる場合、
テーブルを分けるか一つのテーブルを横長くしていくかどっちが良いのだろうか…。

各グループで共通するフィールドが20ぐらい。 … 共通フィールド群とします
各グループにより、個別に必要となるフィールドが、0〜20ぐらい。 … 専用フィールド群とします
グループ数は現在10ありますが、今後も増えていく予定で、その時に必要となるフィールドは現時点では不明です。

共通フィールド群と専用フィールド群は1対1の関係になります。
897NAME IS NULL:2011/06/24(金) 18:45:33.40 ID:???
「いろいろなグループに細分化」するとして同一従業員が複数のグループに属する可能性は?
898896:2011/06/24(金) 19:29:26.48 ID:???
>>897
ありえます。

ちなみにイメージとして以下とかを考えています。
テーブルを一つに纏めた場合は以下の様になるかと思います。
[作業データ]
・日付、社員ID、グループID、共通F1〜20、専用F1〜20

― グループ毎にテーブルを作成 ―――――――――――
[作業データ]
作業ID、日付、社員ID、グループID、共通F1〜20

[グループ1]
作業ID、専用F10

[グループ2]
作業ID、専用F5

[グループ3]
作業ID、専用F20




どうにもしっくりきません。。
899NAME IS NULL:2011/06/24(金) 23:14:42.94 ID:???
作業とグループは1対1なのかn対nなのかとかいろいろあるけど

グループと作業フィールドだけの関係でみるなら
作業フィールドをマスタ化して、グループIDと作業フィールドIDを紐づけるのが正攻法じゃないかな?
900899:2011/06/24(金) 23:16:13.55 ID:???
作業フィールドってなんだ...
フィールドに読み替えてくれ
901NAME IS NULL:2011/06/24(金) 23:16:25.78 ID:???
よくポータルサイトなどである「ユーザの日記や投稿した写真」の
テーブル名をどうするかでかなり悩みます・・。

普通は、diaryやphotoにすると思うのですが、
管理者も更新履歴やを書いたりサイトの写真を投稿する事があるから、
単語だとどっちのユーザ向けのテーブルか分からなくなります。

ですので、user_diaryとかuser_photoにして
テーブルを作成しているのですが、冗長過ぎないかと気になります。

何か良い考え方はないでしょうか?
902 忍法帖【Lv=15,xxxPT】 :2011/06/24(金) 23:52:00.09 ID:???
2単語程度でなら冗長とは思いませんよ。
903NAME IS NULL:2011/06/25(土) 00:25:30.66 ID:gJ5H7vkK
>>896

>>898の書き込みの中に「日付」という情報がありますが、
これについての説明が>>896の文章の中にないですね。

「同一の従業員が複数のグループに属することがある」・・・とのことですが、
同一の従業員が同一日に、複数のグループに属することがあるのですか?

それとも
「同一の従業員が同一日に、複数のグループに属することはない」
言い換えれば、
「社員IDと日付が決まれば、グループIDは決まる」・・・ということでしょうか。

まず、ここを明らかにしたいです。


次に、「作業ID」という情報がありますが、これと「グループID」との関係も、
よく理解できません。

「同一のグループが同一日に、異なる作業をすることがある」・・・ということでしょうか?
「別々のグループが同一日に、同一の作業をすることがある」・・・ということでしょうか?

設計しますので、もう少し詳しく教えてください。
904NAME IS NULL:2011/06/25(土) 01:34:53.45 ID:???
>>901
そもそも、ユーザが登録する日記と管理者が登録する日記を
別テーブルに保存するのかどうかから考えた方がいいんじゃねえか
905NAME IS NULL:2011/06/25(土) 02:16:36.02 ID:???
>>904
それも前に別のスレで言われたのですが、
ユーザと管理者と明らかに用途(と、カラム)が違うので
1つのテーブルを使うというわけにもいかないんです。

一応>>903さんの言うように2単語程度なら冗長にはなりませんが、
割と1単語でまとめているサイトが多いので、なんか気になって・・・
あくまでファイル名は1単語で、テーブルは2単語以上かもしれませんが
906NAME IS NULL:2011/06/25(土) 16:09:34.95 ID:???
>>905
オレのテーブルは、3単語4単語くらい
あたりまえだな。
もっと長いのもある。

非常識はあっても、常識はない。

サイトのってサンプルか解説だろ。
わざわざ簡単にしてるんだよ。
いわせんなはずかしい。
907NAME IS NULL:2011/06/25(土) 17:52:31.59 ID:???
ですよねー
1単語でまとめてるのが多いってのは
例えばURLが/user/diary/になっているのが多いって意味ですが、
テーブル自体は違って当然ですよね。

フレームワーク使って開発する事が多いので、
出来るだけ短くしなければ行けないと悩んでいましたが、
他の人も3単語4単語当たり前だと言う事で安心しました。
908NAME IS NULL:2011/06/25(土) 19:11:31.99 ID:???
このケースこそ、各フィールド全部別々にテーブルにしたら良いのではないかな。
IDをうまく横糸にすれば、洒落たモデルが作れると思うが。
909896:2011/06/27(月) 11:02:07.19 ID:???
>>903
ありがとうございます。分かりづらくてすみません。
グループと言う説明が悪くより分かりづらくしているのかもしれません。。
一般的には工程と言われるものに近いと思います。

>同一の従業員が同一日に、複数のグループに属することがあるのですか?

従業員が、各グループ(工程)で作業をした履歴を残したいという事になります。
各グループへは従業員により、時間単位で異なる人もいれば、ずっと同じ人もいます。

ですので、社員IDと日時が決まってもグループIDが決まる事はありません。

例:
Aさんが、10:00に、グループAにて作業を行った。
(この際登録するのは共通F+グループAの専用F)
Aさんが、11:00に、グループCにて作業を行った。
(この際登録するのは共通F+グループCの専用F)


専用Fは、各グループにより必要な個数や内容(型)が異なります。
グループは、数か月に1,2度追加もしくは削除、もしくは見直しされたりもします。
910NAME IS NULL:2011/06/27(月) 12:30:37.62 ID:72GVkR7S
あるWebシステムで「管理ユーザ」「一般会員」「ビジネス会員」を
1つのusersというテーブルでまとめていました。

私はこれまで、
「admin_users」「users」「biz_users」と3つのテーブルを作って
それぞれの会員用途で分けていたのですが、
前者のように、1つのテーブルでアカウント情報を
まとめるケースって多いのでしょうか?
911NAME IS NULL:2011/06/27(月) 15:02:19.29 ID:???
>>910
テーブルは少ない方が保守が楽なので、同じ属性を持ったエンティティを実装で一つのテーブルにまとめておくことはよくあるよ。
セキュリティや性能・ロック、(それと、フレームワークの制限)とかで問題がある場合だけ物理的な分割を考える。
それ以外ならビューによる分割で十分なことが多いね。

>>909
しょっちゅうスキーマが変わるデータを RDB で真面目に実装しようとすると、
手間の割に見返りは少ないのでテーブルを分けない案のほうをお勧めするよ。
特に履歴みたいなデータは属性の増減が良くあるので、最初は綺麗でも後々穴だらけのテーブルになってることが多いし。
専用の属性は、集計や検索に必要な列のみ抽出して、あとは汎用列1,2,3... や XML 列に入れて使えば良い。
912NAME IS NULL:2011/06/27(月) 15:25:56.73 ID:???
>>911
なるほど。保守性を考えてテーブルを分けないんですね。

ただ、私が>>910で出した用途のテーブルって
「会員プロフィール」とか、「会社情報」とかのテーブルとJOINする
ケースが多いと思うので、結局テーブル数は増える気がするんですけどね。
913NAME IS NULL:2011/06/27(月) 16:10:41.47 ID:???
>>912
その辺りはケースによるでしょ。
テーブルを分ける場合もあれば、汎用の列を作って一つのテーブルで済ませる場合もあるし。
どれが正解ってのはなくて、場合によるよ。
914NAME IS NULL:2011/06/27(月) 16:16:59.92 ID:???
その辺り、「どのケースで分ける・分けない」の判断が難しいですね。
システム作っていて後から分けた方が良いって思う事も良くありますし。

先の事まで見通して設計するべきと言うのもわかるのですが・・。
915NAME IS NULL:2011/06/27(月) 21:57:22.33 ID:???
>>910
個人的な意見ですので、異論もあると思いますが、
自分の場合、まず第一にテーブルを分けることを考えます。

但し、共通項をまとめた情報をスーパータイプとして別に用意し、
スーパータイプには区分(管理ユーザの場合は1、一般会員ユーザの場合は2・・・など)を
持たせます。

*=キー

ユーザ(*ユーザID、ユーザ区分、全ユーザに共通する情報1、全ユーザに共通する情報2・・・)

管理ユーザ(*ユーザID、管理ユーザ独自情報1、管理ユーザ独自情報2、・・・)
一般会員(*ユーザID、一般会員独自の情報1、一般会員独自の情報2、・・・)
ビジネス会員(*ユーザID、ビジネス会員独自の情報1、ビジネス会員独自の情報2、・・・)

このとき、ユーザの区分は排他的であることが条件です。
916NAME IS NULL:2011/06/27(月) 22:02:50.46 ID:???
>>910

排他的というのは、「管理ユーザ兼ビジネス会員」などは存在しない・・・ということです。

1つのテーブルにまとめる方法は、以下の条件の全てを満たした場合に、
始めて検討します。

・各区分に共通する情報が、7割〜8割を超える。
・今後、新たな区分が追加される可能性が無いことが、予め分かっている。
・アプリケーションのロジック上、区分によって扱いを分ける場面より、
 各区分を同列に扱う場面のほうが多いことが、予め分かっている。
917NAME IS NULL:2011/06/27(月) 22:43:00.87 ID:???
・・・ということで、>>896はこんな感じでしょうか。
つまりグループ毎にテーブルを作成するパターンですね。

-------------------------------------------------
社員マスタ(*社員ID、社員名、・・・)

グループマスタ(*グループID、グループ区分、共通F1〜20)
グループ区分_01(*グループID、専用F1〜10、・・・)
グループ区分_02(*グループID、専用F1〜5、・・・)
グループ区分_03(*グループID、専用F1〜20、・・・)

社員作業(*日付、*社員ID、*グループID)
-------------------------------------------------

作業ID(これはIDというよりは、ただの連番ですよね?)
という情報がどうしても必要であれば、
以下のような持ち方でも構わないと思います。
社員作業(*作業ID、日付、社員ID、グループID)

また、
アプリケーションでの見せ方や処理の都合などを踏まえて、
以下のような持ち方のほうが都合がよければ、それでも構わないと思いますよ。
(あまり好きではありませんが・・・)

社員作業(*社員ID、*グループID、*年月、1日稼動フラグ、2日稼動フラグ、・・・、31日稼動フラグ)


>[作業データ]
>・日付、社員ID、グループID、共通F1〜20、専用F1〜20

余談ですが、上記のようにテーブルを一つにまとめる方法をとった場合、
グループAへの作業の割り当てが全くない(一人もいない、1日もない)と、
グループAの専用Fをデータベースに持たせることができなくなります。

言い換えれば、グループAへの作業割り当てを行って初めて、グループAの専用Fが
データベースに登録できることになります。
これは一般的に第1正規形であることの問題点と言われています。
(非キー属性である専用F1〜20が、候補キーの一部であるグループIDに関数従属しているため、第一正規形となります)

いろいろと書きましたが、間違ってたらごめんなさい。
918NAME IS NULL:2011/06/28(火) 04:31:04.31 ID:???
>>914
マルチユーザーなRDBMSのユーザー管理を参考にしたら?
ユーザー+権限・ロールの2ないし3テーブルが定石になってるから
919910:2011/06/28(火) 06:51:19.72 ID:???
>>915-916、918
ご意見ありがとうございます。
私はMySQLを想定しているので、MySQLを使用したOSSを参考にしています。
(例えば、EC CUBEとかOpenPNE)

それで、現状は以下のようなテーブル構成です。
(主な部分のみ記載します)

■管理者用
ID、アカウント名、パスワード、メールアドレス、権限
■一般会員用
ID、メールアドレス、パスワード、ニックネーム、年齢、性別...etc
■ビジネス会員用
ID、メールアドレス、パスワード、会社名・担当者名...etc

管理IDはアカウント名+パスワードでログインさせ、
一般・ビジネスはメールアドレス+パスワードでログインさせるパターンです。

共通項を考えるなら

■ユーザ
ID、アカウント名、パスワード、権限
■一般会員
ユーザID、ニックネーム、年齢、性別...etc

みたいな形になるかと思いますが、上記の通り、
会員によってログイン方法を変えたいので、
共通部分もダブって1テーブルに記載しています。
920910:2011/06/28(火) 06:55:45.79 ID:???
それで>>919のテーブル構成だと凄く無駄が多く感じ、
どのようにまとめれば良いか分からなくなってしまった為、
一からマルチユーザに対するテーブル構成を考えたくて、質問しました。

>>918
その定石となるテーブル構成が分かるOSSのWebシステムってわかりますか?
上記で書いたシステムでは、918さんの言う定石通りになっていません。
921NAME IS NULL:2011/06/28(火) 06:59:55.64 ID:???
分割のメリットがわからない以上、一緒にしとくもんじゃないの。
「ゲスト会員」「VIP会員」「家族会員」とか権限が増えたらテーブル追加する気?
922910:2011/06/28(火) 08:49:28.88 ID:???
今までの考えはテーブル追加する気です。

会員追加してもテーブルにログイン情報だけって事はないでしょうから。
921さんの考えは、「どの会員にどこまでの情報を操作させる」であって、
「どの会員にどの情報を保持する」ではないと思います。
923NAME IS NULL:2011/06/28(火) 09:18:26.04 ID:???
>>920
Mediawiki, Redmine, Drupal, Django, Movable Type
924NAME IS NULL:2011/06/28(火) 16:26:52.67 ID:???
>>910
そしたら↓こうするのはどうだ?

・ユーザ
ID、E-MAIL、パスワード、区分

・一般会員
ユーザID、名前、性別、年齢(一般会員独自の情報)
・ビジネス会員
ユーザーID、会社名、担当者名(ビジネス会員独自の情報)

・管理ユーザ
ID、アカウント名、パスワード、権限(どこまで操作させるかなど)


これであれば、一般・ビジネス会員をまとめられるし、
VIP会員とか家族会員が出来ても専用テーブルと結合するだけだ。

そして管理ユーザは分けてるから、ログイン方法が違う場合にも対処できるし、
仮にプログラムミスがあっても「一般会員の情報で管理画面にログインできた」
と言う問題も避けられる。

確かOpenPNEがこのやり方をしてたはず
925NAME IS NULL:2011/06/28(火) 21:16:53.75 ID:???
>そして管理ユーザは分けてるから、ログイン方法が違う場合にも対処できるし、
>仮にプログラムミスがあっても「一般会員の情報で管理画面にログインできた」
>と言う問題も避けられる。

普通に区分で条件指定すれば、その可能性はほとんど無いと思うんだが。
君のテーブル構成にするなら、管理ユーザもユーザにまとめればいいじゃん。
926NAME IS NULL:2011/06/28(火) 21:21:18.18 ID:???
行レベルセキュリティが必要か、DBMSがサポートしてるか、
その辺で別テーブルにするかどうか考えるかな。俺なら。
927NAME IS NULL:2011/06/29(水) 03:15:25.35 ID:???
一般会員、ビジネス会員という、まったく別な実体の集合があると思うならテーブル分ければ良い
会員という実体があって、その区別として一般とビジネスという区分があると思うなら1テーブルで良い

プログラム的にはどうとでもなるから、どっちがより実情に近いかで決めれば良いんじゃない
928910:2011/06/29(水) 09:03:14.44 ID:???
みなさん、色々とありがとうございます。
はじめは>>915>>924さんの形で行こうと思ってたのですが、
私が開発するシステムでは、各会員毎に個別データがあります。
(一般会員+プロフィール、ビジネス会員+会社情報 など)

ですので、>>927さんの言うように1つのテーブルにまとめる事にしました。

ログイン情報の箇所が重複するので、>>910のような質問をしましたが、
正規化してテーブル構造がややこしくなるより、
分けた方が簡単なので、作りやすい方法で生きたいと思います。

色々とアドバイスいただき、ありがとうございました。
929NAME IS NULL:2011/06/29(水) 10:51:56.41 ID:???
個人情報にidをふるのは登録順にソートするためでしょうか?
タイムスタンプで代替可能ですがidのほうが気楽だからという理由だからでしょうか?
とくに登録順でソートする必要がない場合、
主キーを会員名やメールアドレスにすることができると思いますが、
idを主キーにすることが多いのはなぜなんでしょう?

またidを主キーにする場合、auto_incrementでindex振りを行うと思いますが、
物理削除後に歯抜けになったidは気にする必要もないでしょうか?
idをそのまま出力すると汚いので、プログラム側でidを振りなおして表示すれば問題ないですが、
ちょっと気になります。

特に統計情報を取るわけでもなく、論理削除だけ行い情報を貯めておくというのは良くないと思うので、
削除フラグ的なことはなしでお願いします。
930NAME IS NULL:2011/06/29(水) 11:48:59.68 ID:???
IDだとauto_incrementで連番が付けられるというのもあるし、
単純にテキストサイズが最小で済むという理由もある。
もちろん、ソートするという理由もあるし。
931NAME IS NULL:2011/06/29(水) 11:50:23.95 ID:???
>>929
会員名は同姓同名の場合、重複するため主キーになれない。
会員名・メールアドレス共に変更される可能性があるので、主キーに相応しくない。
主キーに相応しい列がないときは、代替キーとして id を振る。

代替キーはシステムだけが使う値であって、ユーザーに見せるための値じゃない。
なので、ランダムな値や GUID を id に使うこともある。ソートのためじゃない。
932NAME IS NULL:2011/06/29(水) 11:51:23.12 ID:???
>物理削除後に歯抜けになったidは気にする必要もないでしょうか?

に関しても、歯抜けで良いんだよ。
削除したIDをまた振り直したらデータの取り扱いがおかしくなる。

Aさんが投稿した画像ID1を削除した。
歯抜けは嫌なので、Bさんが投稿した画像にID1が付いた。
Aさんの画像だと思ってアクセスした人はBさんの画像が表示されるとおかしいよな?

933NAME IS NULL:2011/06/29(水) 11:57:37.26 ID:???
>>929
IDの意味は一意を保証するだけ。それ以上の意味を持たせちゃいけない

たとえば名前は同姓同名がいるかもしれない
メールアドレスは変更されたり複数の人で共有されているかもしれな
システム側で一意を保証できれば楽で便利だから使うだけ

途中の行が削除された場合に連番で振り直さないとダメなら、
それはIDとは別に連番の項目を持たせるべき
934NAME IS NULL:2011/06/29(水) 12:24:42.61 ID:???
char(n) varchar(n) integer(n)とかnを振らないとだめなんですか?
そんな先を見越した設計なんてできないよぉー
全部最大長の(varcharだったら255?256?)ものを指定するとなんか不都合ですか?
935NAME IS NULL:2011/06/30(木) 11:01:18.48 ID:t8+Q7d0R
複合主キーというものはあまり使わないほうがいいのでしょうか?
INT型の他カラムの主キー(外部キー)とTINYINT型のカラムで構成されています
どのみちその複合キーはUNIQUEでNOT NULLでなくてはならないのですが
複合キーは主キーには使わないほうがいいのでしょうか?

あと長いURLのパスなんかを主キーにするのはやめたほうがいいでしょうか?
UNIQUEでNOT NULLなカラムではありますが
検索パフォーマンス落ちそうな気がするので代理キーにしています

根本的なところで無理に主キーは作らなくてもいいのでしょうか?
936NAME IS NULL:2011/06/30(木) 15:26:23.50 ID:y7l4KxAO
>>934とほぼ同じですが、VARCHAR型のサイズなんですが、100と設定した場合と1000と設定した場合で、
例えば、数万件レコードを登録したが、結局最大で50バイト/レコードしか使わなったとした場合、
レスポンスや容量(テーブルorレコード)に影響がどれぐらいあるのか知っている方いましたら教えてください。
937NAME IS NULL:2011/06/30(木) 15:45:11.48 ID:???
全く影響ない
938NAME IS NULL:2011/06/30(木) 16:05:10.54 ID:???
容量やパフォーマンスより、
根拠のないサイズを指定することで、
その設計を見た人間を混乱させるリスクを考慮すべき。

パフォーマンスが落ちても根拠に基づく必要性があるなら1000と指定すべき。
容量もパフォーマンスも変わらないからといって、
100の指定で十分なものを大は小を兼ねる的に1000とするなら、それはダメ設計。
939NAME IS NULL:2011/06/30(木) 16:56:10.34 ID:???
SQLiteだと関係ないよね
940NAME IS NULL:2011/06/30(木) 17:22:10.73 ID:???
>>935
根本的なところで無理に主キーは作らなくてもいいのでしょうか?
主キーになる項目(の組み合わせ)があるなら、それを主キーにすれば良い

主キーが複合キーだと、結合に毎回たくさんの条件書かないとダメだとか、
取り扱いが不便だと思えば人工的な主キー項目を作れば良い

検索パフォーマンスは、ユニークなインデックス張るならまあ誤差の範囲じゃないかと
ただ、結合に使う項目は、多数のテーブルに同じ項目が存在することになるので
長いテキスト項目なんかだと記憶領域がもったいない気はする

>>936
それはそのDBMSの実装によるので、該当するDBMSのスレで聞いてください
941NAME IS NULL:2011/06/30(木) 17:37:34.62 ID:???
>>937-940
どうもです。

SQL Server 2000 になります。
942NAME IS NULL:2011/07/01(金) 00:33:21.08 ID:???
int型のunsignedについてですが、あまりつけてるのを見かけません。
連番のPKにしても年齢みたいな項目にしても、
つけないのは何か理由があるのでしょうか?
マイナス値は想定してない場合、エラーチェック代わりにはもってこいだと思うのですが。
943NAME IS NULL:2011/07/01(金) 12:59:09.52 ID:???
会員テーブルからVIP会員を5人選ぶとした場合、
どこにそのVIP情報を入れればいいでしょうか?
会員テーブルにNULLなVIPフラグを入れるのは、
正規化的に好ましくないと思いますが、
従属テーブルであるVIPテーブルをわざわざ作るのもどうなのかな?と思います。
どっちにするのが妥当でしょうか?
944NAME IS NULL:2011/07/01(金) 14:48:14.33 ID:???
>>942
標準SQLじゃないからとか
副作用に期待せず明示的にCHECK制約しろやとか
扱える範囲が2倍になっても焼け石に水だろとか
クライアント側が符号無し整数をサポートしていないとか
945NAME IS NULL:2011/07/01(金) 15:27:10.72 ID:???
従属テーブルでないVIPテーブルをわざわざ作る
946NAME IS NULL:2011/07/01(金) 16:32:58.04 ID:???
>>945
でもそれだとSQLが複雑になりませんか?

もしVIP会員の会員情報を削除したい時、
delete文を2つに行わないといけなくなるので。
947NAME IS NULL:2011/07/01(金) 17:20:56.96 ID:???
つon delete

※DBMSによるが
948NAME IS NULL:2011/07/01(金) 17:48:34.29 ID:???
>>947
on deleteって従属テーブルのみ可能なものだと思っていました
早速試してみます
949NAME IS NULL:2011/07/01(金) 19:21:15.35 ID:???
単純なテーブルをcreateしたあとに
細かい設定をalterで設定するか
create時に全部やるのどちらがいいのでしょうか?
950 忍法帖【Lv=16,xxxPT】 :2011/07/01(金) 20:06:12.52 ID:b768LcB7
全商品一覧を表示するときに、

商品番号
商品名
更新日

ぐらいしかソート基準がないのですが、
こちらが選んだ基準でソートをしたい場合、
ソート用のテーブルを作って、
デフォルトに現在の商品数をカウントしたものを入れるみたいにして
作成するのが一般的ですか?

なんか他にベターな方法があったら教えてください。
951NAME IS NULL:2011/07/01(金) 20:10:41.96 ID:???
>>949
どっちでもええ
952NAME IS NULL:2011/07/01(金) 21:41:24.54 ID:???
>>949
SQL文の見やすさで後者の「CREATE時に全部」をすすめます。
953NAME IS NULL:2011/07/01(金) 22:00:28.49 ID:???
>>950
日本語でおk
954NAME IS NULL:2011/07/01(金) 22:08:19.63 ID:???
必要なソートキーをあらかじめ用意するのが一般的です。
955950 忍法帖【Lv=16,xxxPT】 :2011/07/01(金) 22:29:36.05 ID:???
>>954
レスありがとうございます。
例えばソート基準が複数ある場合、
その分だけ商品テーブルにソート1、ソート2みたいな項目を作ればいいんですね?

どこまで正規化すればいいのかわからず困っています。
956NAME IS NULL:2011/07/01(金) 23:30:40.82 ID:???
便乗質問ですが
基本情報はあまり更新しないが
ソート番号だけ頻繁に入れ替えるような場合は専用テーブル作ったほうがいいですか?
テーブル項目が多ければ多いほどアップデート速度が遅くなるなんてことがなければ
分ける必要もないんでしょうけどどうなんでしょう?
joinするセレクトのほうが遅くなれば本末転倒ですが
957NAME IS NULL:2011/07/02(土) 00:00:06.26 ID:???
ソート用の「テーブル」作るなんてことは普通やらない

超大量データを超複雑な条件でソートする場合ぐらいだが
それも今時のDBMSなら、インデックスとか実データ持てるビューとかで対応できる場合がほとんど
958NAME IS NULL:2011/07/02(土) 09:34:29.08 ID:???
>>957さんのおっしゃることで
ユーザ視点の優先順位付けは具体的にどうやればいいのでしょう?

例えば

id 商品名
1 リンゴ
2 オレンジ
3 モモ
4 ブドウ
5 ナシ
6 バナナ
7 マンゴー
8 イチゴ
9 サクランボ

このテーブルの表示順を
5 4 3 2 1 9 8 7 6
にして次回以降ソート順位のつけなおしも
その順番を保ったままにするにはどうすればいいのでしょうか?
959NAME IS NULL:2011/07/02(土) 09:36:40.44 ID:???
何を基準にソートすんの?

ソート順をユーザーが指定する、とかってことなら、それ用のカラムを
用意するしかないでしょ。
960NAME IS NULL:2011/07/02(土) 09:43:22.97 ID:???
>>959
テーブルにソート基準になるデータはありません
好きなように表示順位を入れ替える感じです
それで入れ替えたデータは保持され
また入れ替えたい時に入れ替えるといった感じです

例えば上のほうに表示してるのにも関わらず売れ行きが悪い場合は
ちょっと表示を下に下げて他の売れ行きがいいものを上げてみるか
みたいな感じに使いたいです
961960:2011/07/02(土) 09:47:49.41 ID:???
ごめんなさい
よく考えたら>>960の例だと売上数カウントとかが基準になりますね

とりあえずリストを基準なしに表示したい順番に入れ替えたいということです
962NAME IS NULL:2011/07/02(土) 09:49:23.60 ID:???
そしたら、テーブルを↓みたいにして、ソートキーをUpdateする形だろうね。

id, 商品名, ソートキー
963NAME IS NULL:2011/07/02(土) 09:59:20.04 ID:???
普通はソート順が商品(名)に紐づいてると見てマスタにソート順カラムを含める。
しかし業務フローとしてそんな頻繁にソート順を更新するなら別途テーブル用意したい気もするわな。
まあいずれにせよ>>962でいいと思うが。
964NAME IS NULL:2011/07/02(土) 10:05:39.92 ID:???
>>962-963
どうもありがとうございます
ではその形式にしたいと思います
965NAME IS NULL:2011/07/02(土) 10:09:03.74 ID:???
あー。たとえば、ユーザーごとにソート順を変えられる、とかなら、
もちろんこれじゃダメだよ?
966NAME IS NULL:2011/07/02(土) 10:14:13.49 ID:???
>>965
はい
そこは大丈夫です
967NAME IS NULL:2011/07/02(土) 10:38:30.61 ID:???
連絡先を複数指定して、特に指定がない場合に使う1つを指定するようなものの設計ですが、

int 客id, String 連絡先, bool デフォルト

こんな感じでいいですか?
968967:2011/07/02(土) 10:45:35.64 ID:???
個人的には、

デフォルト連絡先
int PK 客id

とかがあったほうがプログラムが楽なんですけど、
>>967のような構成の場合は、
客idに対してデフォルトにtrueが設定されてるのが1つしかあってはならない
みたいなcheck用SQLを書かないといけないと思うんですけど、
SQLはよくわからなくて。
969NAME IS NULL:2011/07/02(土) 10:58:06.49 ID:???
>>968をちょっと訂正

連絡先
int FK 客id, String 連絡先

デフォルト連絡先
int PFK 客id, String連絡先

みたいな感じです。
970NAME IS NULL:2011/07/02(土) 11:48:37.97 ID:???
>>969
これ、SQLだけで連絡先一覧が取れて楽ですね。デフォルトも考慮されてるし。
971NAME IS NULL:2011/07/02(土) 11:50:54.45 ID:???
わざわざ分けるのが面倒。
972969:2011/07/02(土) 12:37:22.04 ID:???
>>970
ですよね。やっぱり楽ですよね?

>>971
面倒ですか?

客id, 客名, 客会社, 客部署, 連絡先1, 連絡先2, 連絡先3, デフォルト連絡先
これの重複削除で、

客id, 客名, 客会社, 客部署
客id, 連絡先, デフォルト
が多分第一正規化ってやつですよね?

>>969は第何正規化っていうんでしょうか?
973NAME IS NULL:2011/07/02(土) 12:40:08.77 ID:???
客id, 客名, 客会社, 客部署, デフォルト連絡先
連絡先id, 客id, 連絡先

とか?
974969:2011/07/02(土) 12:45:25.53 ID:???
なるほどー
デフォルト連絡先に連絡先idをいれとく訳ですか。
それが正しい第一正規化なんでしょうね。
自分がやろうとしてたことはあまり一般的ではないんでしょうか?
975NAME IS NULL:2011/07/02(土) 14:23:40.07 ID:???
>>974
テーブルが正規化されてるかどうかは、そのテーブル見ただけでは断定できないぞ

たとえば
>客id, 客名, 客会社, 客部署, 連絡先1, 連絡先2, 連絡先3, デフォルト連絡先
だったとしても、連絡先1は固定電話で連絡先2は携帯電話、連絡先3はメールだと決まっているなら
それはこの形式でも正規化されてるといえるかもしれん(項目名がまずいだけ)

まずは要件をちゃんと整理してからテーブル設計してください
976NAME IS NULL:2011/07/03(日) 01:42:34.91 ID:???
あとから機能を追加するとき既存テーブルのカラムに追加するか
別テーブル作るかどちらがいいですかね?
フラグ1個なんですけど

機能追加とわかるようにあえて分けるか
分けるようなものでもないので追加するか

悩みます
977NAME IS NULL:2011/07/03(日) 06:23:07.71 ID:???
業務処理の属性が強いか
テーブルの一部としての属性が強いか
どちらによるかで判断したら
978NAME IS NULL:2011/07/03(日) 06:43:51.79 ID:???
まあ、現実的には既存プログラムの修正とテストにかかる工数次第だな

既存テーブルのレイアウトさわると、そのテーブル使ってるプログラム全てを
テストし直せってことになる場合が多いから、あんまりやらないことが多いんじゃないかと

フラグ1個でテーブル追加すると、キーとフラグ1個だけのテーブルになるわけだが
できればそんなテーブル作りたくないと思うが
979NAME IS NULL:2011/07/03(日) 08:39:44.66 ID:KjioPXpn
>>934
たいていの処理系に、複合主キーをバインドできるコンボボックス
みたいなのは用意されてないから、複合主キーは使わないほうが無難だお
980976:2011/07/03(日) 19:46:07.05 ID:???
>>977-978
ありがとうございます
難しいところですが業務処理の属性が強そうなので
わけようかなと思います

変なテーブルができるのはあんたが追加処理要求してきたからなんだからね!
981NAME IS NULL
こうしてまた調査対象が増える
履歴管理とかしてないのかね