#mysql #sql #database #select
#mysql #sql #База данных #выберите
Вопрос:
В небольшом приложении базы данных библиотеки / исследования, над которым я работаю, у меня есть страница, на которой пользователь может просмотреть все предоставленные им ресурсы.
У меня есть три таблицы для разных ресурсов — книг, журналов и конференций. Таблицы выглядят следующим образом:
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. Поиск в stack overflow и Google для «выбора данных из нескольких таблиц» и другие подобные поиски вернули много результатов для смехотворно сложных объединений, объединений и т. Д. Для баз данных и операций, Которые намного сложнее, чем то, что я пытаюсь сделать здесь.
Разве нет чего-то вроде:
Select * FROM book, journal, conference WHERE mid = 4'
Это возвращает ошибку: «поле mid неоднозначно».
Спасибо!
** РЕДАКТИРОВАТЬ — Как указал Мартинн, большая часть моих проблем связана с дизайном моей базы данных.
Похоже, что два решения заключаются в том, чтобы либо перепроектировать базу book
данных, либо объединить и journal
conference
в одну таблицу resources
или, как очень хитрый обходной путь
Для выполнения трех отдельных запросов:
SELECT * FROM book where mid = 4
SELECT * FROM journal WHERE mid = 4
SELECT * FROM conference WHERE mid =4
а затем объедините эти результирующие наборы с помощью PHP.
Комментарии:
1. вы должны использовать соединение или перекрестное соединение, устанавливая отношения первичных и первичных ключей. И ошибка заключается в том, что mid существует во всей выбранной вами таблице, как запрос знает, на основе какой mid извлекает запись
Ответ №1:
Вероятно, причина, по которой у вас возникли проблемы, связана с дизайном базы данных. Определения трех таблиц (насколько я вижу) идентичны. Возможно, вам следует сделать это одной таблицей с ENUM
полем, указывающим, является ли запись книгой, журналом или конференцией. РЕДАКТИРОВАТЬ: я только что увидел, что это непростой вариант: вам все равно понадобятся отдельные таблицы для информации, относящейся к книгам, журналам и конференциям.
Если вы не хотите этого делать, вам нужно немного подробнее задать свой вопрос. Вы хотите, чтобы строки из трех таблиц были mid
равны 4? В этом случае вы должны использовать UNION
. Если вы хотите, чтобы в одной строке были указаны книга, журнал и конференция mid = 4
, используйте a JOIN
, как уже указывал thomasrutter .
РЕДАКТИРОВАТЬ: теперь, когда вы точно указываете, что вы хотите, чтобы запрос возвращал, вероятно, лучше всего использовать решение «mu is too short». Добавление поля является элегантным решением ( 1 за это).
Тем не менее, я думаю, вам следует рассмотреть возможность использования этой ENUM
опции. Я не знаю, какая функциональность будет нарушена, но исправление запросов сводилось бы к добавлению a WHERE kind = 'journal'
, если вы выбираете из jounals
изначально.
Комментарии:
1. mid — это «идентификатор участника». Поверьте мне, я бы с удовольствием перепроектировал базу данных, но это нарушило бы многие другие функции. В конечном итоге то, чего я пытаюсь достичь, было бы таким же, как если бы вы сделали «ВЫБРАТЬ * ИЗ книги, ГДЕ mid = 4», «ВЫБРАТЬ * ИЗ журнала, ГДЕ mid = 4», «ВЫБРАТЬ * ИЗ конференции, ГДЕ mid = 4» и объединили все эти результирующие наборы в один, если это имеет какой-то смысл. У меня есть метод, который будет проходить через этот массивный результирующий набор и генерировать объекты массива, которые имеют свойства на основе столбцов и их значений. Кстати — как обернуть код в комментарии? пробовал ‘code’ и [code]…
2. решение mu is too short не сработало, поскольку в таблицах разное количество столбцов. Выбор этого в качестве ответа, поскольку это проблема проектирования базы данных (и приложения). Собираюсь стиснуть зубы и попытаться объединить все это в одну таблицу. Спасибо.
3. @sanukcm: Я снова просмотрел ваши таблицы. Основное отличие заключается в дополнительных информационных полях, которые, вероятно, затруднят объединение таблиц (что я должен был видеть ранее). Вероятно, вам лучше выполнить три запроса.
4. @sanukcm: вы можете решить проблемы со схемой с помощью псевдонимов и латералей, чтобы дополнить их, но это было бы немного сложно. Тем не менее, пересмотр вашей схемы звучит как хороший план; возможно, будут работать меньшие фрагменты, но трудно сказать, не зная, как осуществляется доступ к данным и тому подобное. Как обычно, в основном вопрос в том, какой тип боли вы хотите и когда вы этого хотите 🙂
Ответ №2:
Я думаю, вы ищете ОБЪЕДИНЕНИЕ:
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
, чтобы вы могли выяснить, из какой таблицы взята каждая запись.
Ответ №3:
Вы можете достичь этого с помощью объединения.
Самый простой тип соединения в MySQL очень похож на то, что вы уже пробовали. Проблема с тем, что у вас было, заключается в том, что он не знал, на какой «mid» вы ссылались. На самом деле вы хотите объединить все три из них, равные константе.
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 журнала с одинаковым значением «mid», вы получите 4 x 2 x 2 = 16 возвращенных строк. Это потому, что в этом случае вы говорите MySQL «сообщите мне каждую комбинацию книг, конференций и журналов, которые вы можете найти с этими значениями».
Я не знаю, что это за приложение, поэтому я не знаю, хотите ли вы этого. Однако, если вы этого не хотите, и вы просто заинтересованы в получении строк из каждой таблицы по отдельности, а не в их объединении, то, вероятно, это лучше выразить в виде трех отдельных запросов.
Комментарии:
1. Это работает только в том случае, если
mid
есть поле, которое соединяет книги с журналами и конференциями. Для меня не очевидно, что это так. @sanukcm: что означают mid и iid?2. Томас, спасибо за ваш очень наглядный ответ. К сожалению, это работает только в том случае, если пользователь предоставил ресурсы всех трех типов. Если у вас есть пользователь, который, например, отправил только журналы, этот запрос вернул пустой набор.
3. @Martijn Я добавил примечание внизу, теперь немного описывающее это. Я тоже не знаю, хотел ли sanukcm объединять строки на основе
mid
. Итак, я добавил это описание. Приветствия.4. @sanukcm похоже, вам не нужно объединение, и вы хотите запрашивать таблицы отдельно. Таким образом, вы получите список всех книг с этим значением «mid», всех журналов с этим значением и всех конференций с этим значением.
5. @thomas, это именно то, что я хочу. Я думаю, что я просто сделаю три отдельных запроса и объединю их в структуру данных php. Спасибо!