このディレクトリの索引
http://toro.2ch.net/test/read.cgi/db/1316769778/729
#  DBはSQLiteを想定してますが、MySQLでもpostgreSQLでも全然かまいません 
#   
#   
#  採取リスト 
#  |番号|名称|コード|登録日|登録者|公開| 
#   
#  というテーブルがあります。 
#  イメージとして、とある物体がありまして、登録者が各自で次々と登録していきます。 
#  各物体には登録者の間で共有されていてぶれのないコード(A-0001とか)があるものの、 
#  名称に関しては、ある程度の裁量があるため、登録者によって表記にぶれが起きます。 
#   
#  |番号|名称 |コード | 登録日  |登録者|公開| 
#  |01  |クラゲ |A-001|2012/6/1 | 田中 | 1  |  
#  |02  |くらげ |A-001 |2012/6/2 | 鈴木 | 0  | 
#  |03  |海月 |A-001 |2012/6/3 | 佐藤 | 1  | 
#  |04  |クラゲ |A-001|2012/6/4 | 高橋 | 0  | 
#  |05  |ひとで |A-002|2012/6/5 | 小林 | 0  | 
#   
#  番号はオートナンバーで主キー。 
#  登録日はそのままINSERTされた日。 
#  告知フラグは0か1で、外部に公開されていたら1です。 
#   
#  んで、ここから公開されてない行を抜き出すビューを作りたいんです。 
#  CREATE VIEW 未公開リスト (番号, 名称, コード) 
#  AS SELECT 番号, 名称, コード FROM 採取リスト WHERE 公開 = 0 
#  みたいなSQLを走らせると、 
#   
#  |番号|名称  |コード|  
#  |02  |くらげ |A-001| 
#  |04  |クラゲ |A-001| 
#  |05  |ひとで |A-002| 
#   
#  という風になってしまいますが「くらげ」と「クラゲ」で実質的に重複してしまいます。 
#  これを例えば「コードを基準にして重複がないように選んだ」上で、 
#  名称には、特定の登録者の名称を用いてまとめることはできないのでしょうか? 
#  単に、DISTINCTを使うだけでは無理なようですが・・・。 
# 
# 

未公開リスト(_番号,_名称,_コード) :-
        '「コードを基準にして重複がないように選んだ」上で、名称には、特定の登録者の名称を用いてまとめる'(_番号,_名称,_コード).

'「コードを基準にして重複がないように選んだ」上で、名称には、特定の登録者の名称を用いてまとめる'(_番号,_名称,_コード) :-
        名称を登録者で置換したコードならび(_名称を登録者で置換したコードならび),
        採取リスト(_番号,_名称_1,_コード,_登録日,_登録者,0),
        名称を選択(_コード,_名称_1,_名称を登録者で置換したコードならび,_名称).

名称を登録者で置換したコードならび(_重複するコードならび) :-
        setof(_コード,[_番号,_名称,_コード,_登録日,_登録者,_公開] ^ (
                    採取リスト(_番号,_名称,_コード,_登録日,_登録者,_公開)),L1),
        setof([_コード,_名称],[_番号,_名称,_コード,_登録日,_登録者,_公開] ^ (
                    採取リスト(_番号,_名称,_コード,_登録日,_登録者,_公開)),L2),
        名称を登録者で置換したコードならび(L1,L2,_重複するコードならび),!.

名称を登録者で置換したコードならび(L1,L2,名称を登録者で置換したコードならび) :-
        findall([_コード,_],(
                    member(_コード,L1),
                    count(member([_コード,_],L2),_度数)),
                    _度数 > 1),_重複するコードならび),
        名称を早い者勝ちに登録者名に決定する(_重複するコードならび,名称を登録者で置換したコードならび),!.

名称を早い者勝ちに登録者名に決定する([]).
名称を早い者勝ちに登録者名に決定する([[_コード,_登録者]|R]) :-
        採取リスト(_番号,_名称,_コード,_登録日,_登録者,_公開),
        名称を早い者勝ちに登録者名に決定する(R).

名称を選択(_コード,_,_名称を登録者で置換したコードならび,_名称) :-
        member([_コード,_名称],_名称を登録者で置換したコードならび),!.
名称を選択(_コード,_名称,_,_名称) :-
        \+(member([_コード,_],_名称を登録者で置換したコードならび)).