如何从具有多个关联的两个 MySQL 表中检索数据

Posted

技术标签:

【中文标题】如何从具有多个关联的两个 MySQL 表中检索数据【英文标题】:How to retrieve data from two MySQL tables with multiple associations 【发布时间】:2021-11-22 10:02:54 【问题描述】:

我得到了这两个表,其中一个表具有第二个表的多个外键。

rankings

+----------------+--------------+------+-----+---------+----------------+
| Field          | Type         | Null | Key | Default | Extra          |
+----------------+--------------+------+-----+---------+----------------+
| id             | bigint(20)   | NO   | PRI | NULL    | auto_increment |
| search_text    | varchar(255) | YES  | MUL | NULL    |                |
| first_item_id  | bigint(20)   | YES  | MUL | NULL    |                |
| second_item_id | bigint(20)   | YES  | MUL | NULL    |                |
| third_item_id  | bigint(20)   | YES  | MUL | NULL    |                |
| forth_item_id  | bigint(20)   | YES  | MUL | NULL    |                |
+----------------+--------------+------+-----+---------+----------------+

item

+---------------------------+--------------+------+-----+---------+----------------+
| Field                     | Type         | Null | Key | Default | Extra          |
+---------------------------+--------------+------+-----+---------+----------------+
| id                        | bigint(20)   | NO   | PRI | NULL    | auto_increment |
| item_code                 | varchar(255) | YES  | MUL | NULL    |                |
+----------------+--------------+------+-----+---------+---------------------------+

一个ranking 记录可能使用first_item_idsecond_item_idthird_item_idforth_item_id 字段与item 表有多个关联。我想用相应的item_code 而不是item.id 检索ranking 记录。如果我有大量数据,最有效的方法是什么?

PS:item.idfirst_item_id ... tenth_item_id 有 10 个关联。我正在使用 Rails ActiveRecord ORM。任何解决方法都可以。

样本数据ranking

SELECT id,search_text,first_item_id as first,second_item_id as second,third_item_id as third,forth_item_id as forth from rankings limit 10;

+----+-------------+-------+--------+-------+-------+
| id | search_text | first | second | third | forth |
+----+-------------+-------+--------+-------+-------+
|  1 | test 1      |     1 |      2 |     3 |     4 |
|  2 | test 2      |     1 |      2 |     3 |     4 |
|  3 | test 3      |     1 |      2 |     3 |     4 |
|  4 | test 4      |     1 |      2 |     3 |     4 |
+----+-------------+-------+--------+-------+-------+

item 数据示例

SELECT id,item_code from items limit 5;

+--------+------------+
| id     | item_code  |
+--------+------------+
|      1 | 125659     |
|      2 | 125660     |
|      3 | 125661     |
|      4 | 125662     |
+--------+------------+

预期数据

+----+-------------+-------+--------+-------+-------+
| id | search_text | first | second | third | forth |
+----+-------------+-------+--------+-------+-------+
|  1 | test 1      | 125659| 125660 | 125661| 125662|
|  2 | test 2      | 125659| 125660 | 125661| 125662|
|  3 | test 3      | 125659| 125660 | 125661| 125662|
|  4 | test 4      | 125659| 125660 | 125661| 125662|
+----+-------------+-------+--------+-------+-------+

【问题讨论】:

一般来说,你最好的选择是在这里加入“item”四次。四是一个合理的数字。如果从性能的角度来看这太昂贵,请确保您有适当的索引或重新考虑您的数据模型。但是,如果这只是一个简化的情况,并且您有几十个项目列,您可以 UNPIVOT、加入,然后 PIVOT。其语法将取决于您的 DBMS。 不,同一个表有 10 个关联,我的 DBMS 是 mysql。有什么建议吗? 您能提供样本数据和预期结果吗? @Ragnar921 10 有点灰色地带。 MySQL 似乎不支持任何不错的 unpivot/pivot 函数。因此,您将执行 UNION 以取消透视,然后加入,然后执行一系列 CASE 语句以进行透视。不过,这对数据模型来说有点难闻,如果你规范化这个“排名”表的生活会更容易。 @Austin 更新了问题,请检查。 【参考方案1】:

多次(甚至很多次)加入表应该不是问题,因为您是在主键上加入的,即您有一个将要使用的索引。

select 
  r.id,
  r.search_text,
  i1.item_code as item_code_1,
  i2.item_code as item_code_2,
  i3.item_code as item_code_3,
  i4.item_code as item_code_4
from rankings r
left join item i1 on i1.id = r.first_item_id
left join item i2 on i2.id = r.second_item_id
left join item i3 on i3.id = r.third_item_id
left join item i4 on i4.id = r.forth_item_id
order by r.id;

我在这里使用外连接,因为您的所有项目列都可以为空。

【讨论】:

以上是关于如何从具有多个关联的两个 MySQL 表中检索数据的主要内容,如果未能解决你的问题,请参考以下文章

如何使用公共列从多个表中检索数据

数据库:如何从具有一个公共列的两个表中获取多个值

在 Access 2013 中具有多个条件的 DoCmd.SearchForRecord

如何从具有多个表的 IDataReader 中检索值

从具有多对多关系 django 的两个表中过滤数据

MySQL必知应会-第4章-检索数据