2010-05-12 2 views
1

Мне нужна помощь в сложном SQL-запросе. Вот моя настройка: есть две таблицы, одна с авторами, а другая с книгами. Таблица книг содержит поле с именем «автор», которое содержит идентификатор автора. Если в книге более одного автора, то поле «автор» будет содержать все идентификаторы авторов, разделенные символом «;» (что-то вроде 2; 34; 234).Нужна помощь по сложному SQL-запросу

На веб-сайте я должен перечислить все книги, написанные автором. Если есть только один автор, это просто, но как я могу получить те книги, в которых меня интересует автор, второй или третий автор?

Большое спасибо.

ответ

1

Если вы можете, измените схему. Попробуйте справочную таблицу с AuthorPosition, например, так:

BookID AuthorID AuthorPosition 
1  1   1 
1  2   2 
1  4   3 
2  3   1 
2  1   2 

Затем, если вам нужен второй автор, вы можете запросить AuthorPosition = 2.

Если вы не можете изменить схему, вы можете получить все книги (возможно, даже использовать LIKE-запрос, хотя я не уверен, как), а затем проанализировать в бизнес-коде авторы, которых вы хотите.

+1

Я думаю, что он может упростить его, просто имея таблицу карт с 'BookID' и' AuthorID' в виде столбцов.Он привел пример «Меня интересует второй или третий автор», чтобы проиллюстрировать этот вопрос, а не потому, что в ближайшее время ему придется искать «AuthorPosition = 2». Надеюсь, по крайней мере. – Phil

2

Это пример плохого дизайна стола. В идеале у вас было бы 3 стола books, books2authors, authors.
books2authors будет содержать book_id и author_id, и, таким образом, в одной книге может быть больше авторов, и вы можете легко работать с ними в SQL.

Если вы не можете изменить дизайн, я бы пошел с получением всех книг, разобрав поле author_id, и если вы хотите получить только второго автора, введите дополнительный запрос select * from authors where id = <second_author>, чтобы получить необходимую информацию.

+0

Спасибо за урок дизайна стола! Возможно, мне придется использовать его в проекте, над которым я сейчас работаю, и имеет неизвестное количество параметров для каждой записи. – dclowd9901

1

Если вы не можете изменить схему использовать interesection таблицу (например, BooksAuthors), то что-то вроде следующего должно работать:

... 
where AuthorID = '42' 
    or AuthorID = '42;%' 
    or AuthorID = '%;42;%' 
    or AuthorID = '%;42' 

Только первые два из этих положений можно использовать индексы хотя, поэтому поиск авторов, отличных от первого, будет медленнее.

+1

Вы правы, это будет * болезненно * медленным на столе среднего размера. Если это вообще возможно, следует использовать таблицу пересечений. – Piskvor

0

Можете вы изменить таблицы БД?

Вы должны поместить идентификаторы книги и автора в собственную таблицу (таблицу соединений).

Эта таблица (возможно, называется book_author) просто есть идентификаторы для книг и авторов, так что вы можете выполнять запросы, как:

select a.* from book b, book_author ba, author a 
where 
    b.id == ba.book_id 
    and 
    a.id == ba.author_id 
    and 
    b.id = 123; 

вернуть всех авторов для книги с идентификатором 123.

+0

К сожалению, я не могу изменить таблицы. – Psyche

0

Я рекомендую вам внести небольшое изменение: замените; разделитель с, (запятая). Тогда вы можете сделать это:

select b.* 
from authors a 
inner join books b on find_in_set(a.id, b.author) >0; 

Это хороший пример кошмаров данных плохим дизайном. Запрос должен работать, но он всегда будет выполнять полное сканирование таблицы (очень медленно, когда таблицы становятся больше).