2012-02-10 28 views
-1

私は出版データベースを持っており、著者に関するいくつかの情報を取得する必要があります。著者フィールドは、例えばLudlum、R.; Grisham、J。;としてデータベースに保存されているRobert LudlumおよびJohn Grishamという2人の著者がある書籍の場合、著者が1つのフィールドでまとめてまとめたものである。 特定の著者が自分の名前をクリックすると、そのアプリケーションは情報をスプールして書籍のデータを取得する必要があります。私は、著者の姓を参照する変数であるデータカンマ区切りのフィールドからデータを取得するSQL

$select = "SELECT tblPublications.Title, tblPublications.Year FROM tblPublications WHERE tblPublications.Authors LIKE '%$sname%'"; 

$snameを取得するために、この文を使用しています。この問題は、2人の著者が同じ姓を共有する場合に発生します。しかし、私が実装しようとしている回避策は、アプリケーションを姓にしてカンマを挿入し、ユーザーのファーストネームを取得して最初の文字を取得し、結果を文字列に結合し、それらをそれぞれのカンマ区切りの値私が探しているグリッサムの本なら、私は* グリムハム、J. *を私の質問に使用します。 PHP、MYSQLでこれを行う方法はありますか?

+2

TABLE books ------------ id primary key other book data TABLE authors -------------- id primary key lastname varchar (indexed) other author data TABLE author_book_link ---------------------- author_id book_id PRIMARY KEY ab (author_id, book_id) 

今、あなたのようなものを使用して非常に高速なインデックスを使用して照会することができます。非原子的なデータを1つの列に格納することは、パフォーマンス上の理由から*絶対に必要な場合を除いて、悪い習慣です*(あなたがGoogleや何かをしている場合を除きほとんど事実はありません) – FtDRbwLXw6

+1

データベース内のCSVデータ1つの本に複数の著者がいる場合は、別の著者表を作成し、リンク表を使用して書籍を著者にリンクしてください。 – Johan

+0

出版物が保管されている場所は私の外です。私はそれが混沌であることを私が信じている私はそれが混乱していることを知っています – MaxI

答えて

0

これは、ユーザーからどの入力が得られているかによってまったく異なります。

ユーザーが名前を入力するだけでは、あまりできないことがあります(解析するための正しい形式で入力する保証がないため)。

あなたがそれらをしかし、姓と名を入力するために取得している場合は、このような何かを行うことができます。

<?php 
    $firstname = trim(mysql_real_escape_string($_GET['fname'])); 
    $surname = trim(mysql_real_escape_string($_GET['sname'])); 
    $firstletter = substr($_GET['fname'],0,1); 
    $sname = $surname.', '.$firstletter; 
    $select = "SELECT tblPublications.Title, 
      tblPublications.Year 
      FROM tblPublications 
      WHERE tblPublications.Authors LIKE '%$sname%'"; 
+0

'のような' $ lastname% ''は非常に近い結果になります。外側のクエリを使用して、これらの結果に' $ firstname'の出現を見つけることができます。 – Johan

+0

@Johan元の質問で彼が言ったように、 'Ludlum、R.; Grisham、J。;のようなデータベースで、' Grisham、J'を検索していた場合、あなたは大手のワイルドカードを使わないと見つけることができません。 – Nick

+0

質問を読み返した後、私はあなたの意見を見ます。ワイルドカードがうまくいくので(データベースを変更する必要のない唯一の解決策)、誰があなたを落胆させたのだろうか。 +1はドライブバイダウンワードをオフセットします。 – Johan

2

それはデータベースを再設計することが可能である場合、あなたはおそらく、authorsテーブルとAを持っている必要がありますbook_authorsテーブルで、書籍を著者に関連付けるので、複数の著者を各書籍に関連付けることができます。姓はどこから来るのですか?姓、名字の最初の文字を生成することは可能ですか?もしそうなら、おそらく最初の文字が含まれるようにリンクを変更することができます。しかし、同じ姓と名の最初の文字を持つ2人の作者を持つことはまだ可能です。だから、私は最高の解決策は、著者テーブルとBook_authorsテーブルを持って、単に著者IDを隠しフィールドとして保存し、それを使って選択した著者が本を取り出すことだと思います。

+0

「隠しフィールド」とはどういう意味ですか? – Johan

+0

Jon

1

データベース設計が間違っています。データを正規化していません。
likeを使用して主要なワイルドカードを検索すると、インデックスを使用する機会がなくなります。
修正する唯一の方法(誤ったCSVデータを保持したい場合)は、テーブルをMyISAMフォーマットに変換し、FULLTEXTインデックスをauthorsフィールドに置きます。

その後、

SELECT fielda, b,c FROM table1 WHERE MATCH(authors) against ('$lastname') 

参照を使用して、著者を検索することができます。http://dev.mysql.com/doc/refman/5.0/en/fulltext-search.html

もちろん、より良いオプションは、データベースを正規化し、リンクテーブルを持つ作家のための別々のテーブルを作成することです。あなたのスキーマを正規化する必要があり

SELECT b.name, b.ISBN, a.name 
FROM books b 
INNER JOIN author_book_link ab ON (ab.book_id = b.id) 
INNER JOIN author a ON (a.id = ab.author_id) 
WHERE a.lastname = '$lastname' 
関連する問題