Получить данные из нескольких таблиц в одном наборе результатов в MySQL - PullRequest
1 голос
/ 18 октября 2011

В небольшом приложении библиотеки / исследовательской базы данных, над которым я работаю, у меня есть страница, на которой пользователь может просматривать все отправленные им ресурсы.

У меня есть три таблицы для разных ресурсов - Книги, Журналы и Конференции.Таблицы выглядят так:

mysql> desc book;
+---------------+------------------+------+-----+---------+----------------+
| Field         | Type             | Null | Key | Default | Extra          |
+---------------+------------------+------+-----+---------+----------------+
| id            | int(10) unsigned | NO   | PRI | NULL    | auto_increment |
| author        | varchar(255)     | YES  |     | NULL    |                |
| publishedyear | char(4)          | YES  |     | NULL    |                |
| title         | varchar(255)     | YES  |     | NULL    |                |
| edition       | int(3) unsigned  | YES  |     | NULL    |                |
| publisher     | varchar(100)     | YES  |     | NULL    |                |
| place         | varchar(50)      | YES  |     | NULL    |                |
| image         | varchar(100)     | YES  |     | NULL    |                |
| isbn          | varchar(20)      | YES  |     | NULL    |                |
| callnumber    | varchar(30)      | YES  |     | NULL    |                |
| status        | int(1) unsigned  | YES  |     | NULL    |                |
| abstract      | text             | YES  |     | NULL    |                |
| toc           | text             | YES  |     | NULL    |                |
| problems      | text             | YES  |     | NULL    |                |
| futurework    | text             | YES  |     | NULL    |                |
| registered    | datetime         | YES  |     | NULL    |                |
| mid           | int(10) unsigned | NO   | MUL | NULL    |                |
| iid           | int(10) unsigned | NO   | MUL | NULL    |                |
+---------------+------------------+------+-----+---------+----------------+
18 rows in set (0.00 sec)

mysql> desc journal;
+---------------+------------------+------+-----+---------+----------------+
| Field         | Type             | Null | Key | Default | Extra          |
+---------------+------------------+------+-----+---------+----------------+
| id            | int(10) unsigned | NO   | PRI | NULL    | auto_increment |
| author        | varchar(255)     | YES  |     | NULL    |                |
| publishedyear | char(4)          | YES  |     | NULL    |                |
| title         | varchar(255)     | YES  |     | NULL    |                |
| journaltitle  | varchar(255)     | YES  |     | NULL    |                |
| volume        | int(3) unsigned  | YES  |     | NULL    |                |
| issue         | int(5) unsigned  | YES  |     | NULL    |                |
| pagenumbers   | varchar(15)      | YES  |     | NULL    |                |
| image         | varchar(100)     | YES  |     | NULL    |                |
| isbn          | varchar(20)      | YES  |     | NULL    |                |
| callnumber    | varchar(30)      | YES  |     | NULL    |                |
| status        | int(1) unsigned  | YES  |     | NULL    |                |
| abstract      | text             | YES  |     | NULL    |                |
| toc           | text             | YES  |     | NULL    |                |
| problems      | text             | YES  |     | NULL    |                |
| futurework    | text             | YES  |     | NULL    |                |
| registered    | datetime         | YES  |     | NULL    |                |
| mid           | int(10) unsigned | NO   | MUL | NULL    |                |
| iid           | int(10) unsigned | NO   | MUL | NULL    |                |
+---------------+------------------+------+-----+---------+----------------+
19 rows in set (0.00 sec)

mysql> desc conference;
+----------------+------------------+------+-----+---------+----------------+
| Field          | Type             | Null | Key | Default | Extra          |
+----------------+------------------+------+-----+---------+----------------+
| id             | int(10) unsigned | NO   | PRI | NULL    | auto_increment |
| author         | varchar(255)     | YES  |     | NULL    |                |
| publishedyear  | char(4)          | YES  |     | NULL    |                |
| title          | varchar(255)     | YES  |     | NULL    |                |
| conferencename | varchar(255)     | YES  |     | NULL    |                |
| location       | varchar(100)     | YES  |     | NULL    |                |
| conferencedate | varchar(15)      | YES  |     | NULL    |                |
| pagenumbers    | varchar(15)      | YES  |     | NULL    |                |
| image          | varchar(100)     | YES  |     | NULL    |                |
| isbn           | varchar(20)      | YES  |     | NULL    |                |
| callnumber     | varchar(30)      | YES  |     | NULL    |                |
| status         | int(1) unsigned  | YES  |     | NULL    |                |
| abstract       | text             | YES  |     | NULL    |                |
| toc            | text             | YES  |     | NULL    |                |
| problems       | text             | YES  |     | NULL    |                |
| futurework     | text             | YES  |     | NULL    |                |
| registered     | datetime         | YES  |     | NULL    |                |
| mid            | int(10) unsigned | NO   | MUL | NULL    |                |
| iid            | int(10) unsigned | NO   | MUL | NULL    |                |
+----------------+------------------+------+-----+---------+----------------+
19 rows in set (0.00 sec)

То, что я пытаюсь сделать, очень просто, но я не могу найти простую команду SQL дляЭто.Поиск по переполнению стека и google для «выбора данных из нескольких таблиц» и другие подобные поиски дали много результатов для смехотворно сложных объединений, объединений и т. Д. Для баз данных и операций, которые намного сложнее, чем то, что я пытаюсь сделать здесь.

Нет ли что-то вроде:

Select * FROM book, journal, conference WHERE mid = 4'

Это возвращает ошибку: "середина поля неоднозначна".

Спасибо!

** РЕДАКТИРОВАТЬ - Как отметил Мартин, большая часть моей проблемы связана с дизайном моей базы данных.

Два решения, по-видимому, заключаются в том, чтобы либо перепроектировать базу данных и объединить book, journal и conference в одну таблицу resources

или, в качестве очень хакерского обходного пути

Чтобы выполнить три отдельных запроса:

SELECT * FROM book where mid = 4

SELECT * FROM journal WHERE mid = 4

SELECT * FROM conference WHERE mid =4

, а затем объединить эти наборы результатов с помощью PHP.

Ответы [ 3 ]

5 голосов
/ 18 октября 2011

Я думаю, что вы ищете UNION:

select 'book' as item_type, * from book where mid = 4
union all
select 'journal' as item_type, * from journal where mid = 4
union all
select 'conference' as item_type, * from conference where mid = 4

Предполагая, конечно, что вы пытаетесь искать все три таблицы одновременно, и они действительно имеют одинаковую структуру столбцов.В реальном приложении вы, конечно, явно перечислили бы столбцы, а не *, чтобы столбцы располагались в правильном порядке.Кроме того, я взял на себя смелость добавить item_type, чтобы вы могли выяснить, откуда таблица для каждой записи.

5 голосов
/ 18 октября 2011

Вероятно, причина у вас проблемы из-за дизайна базы данных. Определения трех таблиц (насколько я вижу) идентичны. Возможно, вам следует составить одну таблицу с полем ENUM, указывающим, является ли запись книгой, журналом или конференцией. РЕДАКТИРОВАТЬ: я только что видел, что это не простой вариант: вам все равно понадобятся отдельные таблицы для информации, специфичной для книг, журналов и конференций.

Если вы не хотите этого делать, вам нужно еще немного задать свой вопрос. Хотите ли вы иметь строки из трех таблиц, у которых mid равно 4? В этом случае вы должны использовать UNION. Если вы хотите, чтобы одна строка содержала книгу, журнал и конференцию с mid = 4, используйте JOIN, как указывал Томасруттер.

РЕДАКТИРОВАТЬ: теперь, когда вы указываете, что именно вы хотите, чтобы запрос возвращал, вероятно, лучше всего использовать решение "mu is too short". Добавление поля - элегантное решение (+1 за это).

Тем не менее, я думаю, вам следует рассмотреть возможность использования опции ENUM. Я не знаю, какие функции будут нарушены, но исправление запросов сводится к добавлению WHERE kind = 'journal', если вы выбираете из jounals изначально.

4 голосов
/ 18 октября 2011

Этого можно достичь с помощью объединения .

Простейший тип объединения в MySQL очень похож на тот, который вы уже пробовали.Проблема с тем, что у вас было, в том, что он не знал, на какую «середину» вы ссылались.В действительности вы хотите объединить все три из них равными константе.

SELECT * FROM book, journal, conference
WHERE book.mid = 4 AND journal.mid = 4 AND conference.mid = 4

Что должно быть довольно легко понять.

Существуют и другие способы выразить одно и то же соединение -например:

SELECT * FROM
  book
  INNER JOIN journal ON journal.mid = book.mid
  INNER JOIN conference ON conference.mid = book.mid
WHERE
  book.mid = 4

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

Следует отметить, что объединения предназначены для случаев, когда вы хотите объединить строк из таблиц.Если существует несколько конференций или несколько книг и т. Д., Все с требуемым значением «mid», то для каждой комбинации будет возвращена строка.Таким образом, если есть 4 книги, 2 конференции и 2 журнала с одинаковым «средним» значением, вы получите 4 x 2 x 2 = 16 строк.Это связано с тем, что в данном случае вы говорите MySQL: «расскажите мне каждую комбинацию книги, конференции и журнала, которую вы можете найти с этими значениями».

Я не знаю, что такое приложение, поэтому я нене знаю, если это то, что вы хотите.Однако, если вам это не нужно, и вы просто заинтересованы в извлечении строк из каждой таблицы отдельно, а не в их объединении, то, вероятно, это лучше выразить в виде трех отдельных запросов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...