このディレクトリの索引

# 出典 :: SQL質疑応答スレ 12問目 #649 # SQLというよりテーブル設計の質問なんですがいいでしょうか? # # ユーザごとの日々変化するデータを1日1レコードずつ保存するために # 以下のようなテーブル構造を考えました。 # # USERSテーブル #  user_no (ユーザ番号 PK) #  latest_gen_no (最新世代番号) #  氏名その他の属性 # # RECORDSテーブル #  user_no (ユーザ番号 PK*) #  gen_no (世代番号 PK*) #  日々変化する値 # *user_no, gen_no のペアでPK # # GENERATIONSテーブル #  gen_no (世代番号 PK) #  date (日時) # # 全ユーザの最新世代の値を取得するべく、 # select ... from users u, records r # where u.user_no=r.user_no and u.latest_gen_no=r.gen_no; # というSQLを発行すると、ものすごく時間が掛かります。 # # PKやインデックスの設定の仕方に問題があるのでしょうか? # そもそもテーブルの構成がまずいでしょうか? # テーブル副目標(_テーブル名,_引数ならび,_属性名ならび,_副目標) :- findall(_,テーブル定義(_テーブル名,_,_属性名),_引数ならび), 属性名ならびを得る(_テーブル名,_属性名ならび), _副目標 =.. [_テーブル名|_引数ならび]. 属性名ならびを得る(_テーブル名,_属性名ならび) :- setof([_属性順位,_属性名],[_テーブル名,_属性順位,_属性名] ^ テーブル定義(_テーブル名,_属性順位,_属性名),_属性順位_属性名ならび), findall(_属性名,member([_,_属性名],_属性順位_属性名ならび),_属性名ならび). 'USERSテーブルを最新世代に更新する' :- ユーザごとの現在の最新世代を得る(_ユーザごとの最新世代ならび), 'USERSテーブルを更新する'(_ユーザごとの最新世代ならび). ユーザごとの現在の最新世代を得る(_ユーザごとの最新世代ならび) :- 'テーブル副目標'('USERS',[_ユーザ番号,_最新世代番号|_氏名その他の属性],_,_USERS), findsetof(_ユーザ番号,_USERS,_対象ユーザ番号ならび), ユーザごとの現在の最新世代を得る(_対象ユーザ番号ならび,_ユーザごとの最新世代ならび). ユーザごとの現在の最新世代を得る([],[]). ユーザごとの現在の最新世代を得る([_ユーザ番号|R1],[[_ユーザ番号,_最新世代番号]|R2]) :- テーブル副目標('RECORDS',[_ユーザ番号,_世代番号|_],_,_RECORDS), findmax([_日時,_世代番号],( 'USERSテーブルの日時、世代番号'(_RECODRS,_世代番号,_日時)),[_,_最新世代番号]), ユーザごとの現在の最新世代を得る(R1,R2). 'USERSテーブルの日時、世代番号'(_RECODRS,_世代番号,_日時) :- _RECORDS, 'GENERATIONS'(_世代番号,_日時). 'USERSテーブルを更新する'([]). 'USERSテーブルを更新する'([[_ユーザ番号,_最新世代番号]|R]) :- 'テーブル副目標の最新世代番号情報を更新する'(_ユーザ番号,_最新世代番号), 'USERSテーブルを更新する'(R),!. 'テーブル副目標の最新世代番号情報を更新する'(_ユーザ番号,_最新世代番号) :- テーブル副目標('USERS',[_ユーザ番号,_|_氏名その他の属性],_,_USERS_1), テーブル副目標('USERS',[_ユーザ番号,_最新世代番号|_氏名その他の属性],_,_USERS_2), 'USERSテーブルの更新'(_USERS_1,_USERS_2). 'USERSテーブルの更新'(_USERS_1,_USERS_2) :- retract(_USERS_1), assertz(_USERS_2).