2012-02-10 40 views
-1

我有一個出版物數據庫,我需要獲取有關作者的一些信息。作者的領域是這樣的,作者被集中在一個領域,例如,如果一本書有兩個作者,稱爲羅伯特Ludlum和約翰Grisham,在數據庫中它被保存爲Ludlum,R.; Grisham,J .; 如果用戶點擊他們的名字,我的應用程序需要對特定作者創作的書籍進行假脫機信息和檢索數據。我使用這個語句來檢索數據從逗號分隔的字段中檢索數據SQL

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

$sname是指作者的姓的變量。如果兩位作者共用同一個姓氏,則會出現問題。然而我試圖實現的解決方法是讓應用程序採用姓氏,插入逗號,取出用戶的名字並獲得第一個字母,然後將結果合併爲一個字符串,並將它們與作者中每個逗號分隔的值進行匹配字段,例如,如果它是Grisham的書我在尋找我使用* Grisham,J. *在我的查詢。 任何想法如何在PHP,MYSQL中做到這一點?

+2

你應該正常化的架構。將非原子數據存儲在單個列中是不好的做法,除非您絕對必須出於性能原因*(除非您是Google或其他人,否則絕對不會這麼做) – FtDRbwLXw6 2012-02-10 14:53:50

+1

您絕對不應該在數據庫中使用CSV數據,它會一次又一次地咬你,如果一本書可以有多個作者,那麼創建一個單獨的作者表並使用一個鏈接表來將書籍鏈接到作者 – Johan 2012-02-10 14:57:27

+0

存儲出版物的地方超出了我的範圍,我沒有創建該數據庫。相信我我知道它是混亂的作者被集中在一起 – MaxI 2012-02-10 16:14:46

回答

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

使用帶'like'的引導通配符將會消滅任何使用索引的機會如果你知道數據是「姓氏,首字母縮寫」,那麼簡單的搜索'LIKE' $ lastname%''會給出非常接近的結果,你可以使用一個外部查詢來查找這些結果中出現的'$ firstname' – Johan 2012-02-10 14:55:24

+0

@Johan正如他在原始問題中說的,作者在像'Ludlum,R.; Grisham,J。'這樣的數據庫 - 所以在這種情況下,如果你正在尋找'Grisham,J',你不會找到它,除非你使用領先的通配符。 – Nick 2012-02-10 15:04:28

+0

重讀這個問題我明白了你的觀點。我不知道誰低估了你,因爲通配符會起作用(並且它是唯一不需要更改數據庫的解決方案)。 +1來抵消drive-by downvote。 – Johan 2012-02-10 15:07:34

2

如果有可能重新設計數據庫時,你應該有一個authors表和book_authors將書籍與作者相關聯的表格,以便多個作者可以與每本書相關聯。用戶點擊的姓氏來自哪裏?是否有可能生成的鏈接是姓氏,名字的第一個字母?如果是這樣,那麼你可以改變鏈接,所以它會包含第一個字母。但仍有可能有兩位作者具有相同的姓氏和名字的第一個字母。所以我認爲最好的解決方案是創建一個authors表和一個Book_authors表,並將作者id存儲爲隱藏字段,並使用它來檢索選定作者的書籍。

+0

「隱藏字段」是什麼意思? – Johan 2012-02-10 15:08:18

+0

」/> – Jon 2012-02-10 15:44:54

1

您的數據庫設計不正確,您尚未對數據進行標準化。
如果您使用like使用領先的通配符進行搜索,那麼您將終止使用索引的任何機會。
解決您的唯一選擇(如果您想保留錯誤的CSV數據)是將表格轉換爲MyISAM格式,並在authors字段中輸入FULLTEXT索引。

然後,您可以搜索使用

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

見作者:http://dev.mysql.com/doc/refman/5.0/en/fulltext-search.html

當然是一個更好的選擇是標準化數據庫,並創建一個單獨的表與鏈接表的作者。

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) 

現在,您可以查詢使用非常快的指數使用類似:

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' 
相關問題