从逗号分隔的字段中检索数据SQL

问题描述:

我有一个出版物数据库,我需要获取有关作者的一些信息。作者的领域是这样的,作者被集中在一个领域,例如,如果一本书有两个作者,称为罗伯特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

这完全取决于你从用户那里得到什么输入。

如果用户只是输入一个名字,那么你可以做的事情并不多(因为不能保证他们会以正确的格式输入它来解析)。

如果你让他们输入一个名字和姓氏然而,这样的事情可以做:

<?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

如果有可能重新设计数据库时,你应该有一个authors表和book_authors将书籍与作者相关联的表格,以便多个作者可以与每本书相关联。用户点击的姓氏来自哪里?是否有可能生成的链接是姓氏,名字的第一个字母?如果是这样,那么你可以改变链接,所以它会包含第一个字母。但仍有可能有两位作者具有相同的姓氏和名字的第一个字母。所以我认为最好的解决方案是创建一个authors表和一个Book_authors表,并将作者id存储为隐藏字段,并使用它来检索选定作者的书籍。

+0

“隐藏字段”是什么意思? – Johan 2012-02-10 15:08:18

+0

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

您的数据库设计不正确,您尚未对数据进行标准化。
如果您使用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'