从MySQL中的一个结果集中的多个表中获取数据

时间:2011-10-18 07:21:33

标签: mysql sql database select

在我正在处理的小型图书馆/研究数据库应用程序中,我有一个页面,用户可以在其中查看他们提交的所有资源。

我有三张不同资源的表格 - 书籍,期刊和会议。表格如下所示:

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命令。搜索堆栈溢出和谷歌“从多个表中选择数据”和其他类似的搜索返回了很多结果,对于数据库和操作来说,这些复杂的连接,联合等等比我在这里尝试的要复杂得多。

是否有类似的东西:

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

这会返回一个错误:“field mid is ambiguous”。

谢谢!

**编辑 - 正如martijn指出的那样,我的很多问题都来自我的数据库设计。

两个解决方案似乎是重新设计数据库并将bookjournalconference合并到一个表resources

或者,作为一种非常糟糕的解决方法

要执行三个单独的查询:

SELECT * FROM book where mid = 4

SELECT * FROM journal WHERE mid = 4

SELECT * FROM conference WHERE mid =4

然后使用PHP组合这些结果集。

3 个答案:

答案 0 :(得分:5)

我认为你正在寻找一个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,以便您可以找出每个条目来自哪个表。

答案 1 :(得分:5)

可能是因为数据库设计而遇到麻烦的原因。这三个表的定义(据我所知)是相同的。也许您应该使用ENUM字段创建一个表,指定该条目是书籍,期刊还是会议。 编辑:我刚刚看到这不是一个简单的选择:你仍然需要单独的表格来获取特定于书籍,期刊和会议的信息。

如果您不想这样做,则需要指明一些问题。你想让三个表中mid等于4的行吗?在这种情况下,您必须使用UNION。如果您希望一行为您提供有mid = 4的书籍,期刊和会议,请使用JOIN,正如thomasrutter已经指出的那样。

编辑:既然你指出了你想要查询的确切内容,那么最好使用'mu is too short'的解决方案。添加字段是一个优雅的解决方案(+1为此)。

不过,我认为您应该考虑使用ENUM选项。我不知道哪些功能会破坏,但如果您最初从WHERE kind = 'journal'进行选择,则修复查询会归结为添加jounals

答案 2 :(得分:4)

您可以使用 join 来实现此目的。

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子句分开可能会让你更好地阅读 - 一旦你熟悉了语法。

应该注意的是,当您想要从表中组合行时,联接是有用的。如果有多个会议或多本书籍等都具有所需的“中间”值,则会为这些组合返回一行。因此,如果有4本书,2个会议和2个具有相同“中间”值的期刊,您将获得4 x 2 x 2 = 16行返回。这是因为在这种情况下,你告诉MySQL“告诉我你能用这些价值找到的书籍,会议和期刊的每一个组合”。

我不知道应用程序是什么,所以我不知道这是不是你想要的。但是,如果您不想这样做,并且您只想分别从每个表中检索行而不是将它们组合起来,那么它可能更好地表示为三个单独的查询。