Mysql 跨6个表查询,有更好的方法吗?
我所做的是,我希望每个用户都有自己的“唯一”编号系统。我没有将项目编号自动递增1,而是这样做的,Bob的第一个项目将从#1开始,Alice的编号也将从#1开始。房间和类别也是如此。我通过为项目、房间和类别创建“映射”表来实现这一点 下面的查询可以工作,但我知道它肯定可以重构。我在每个表中都有主键(在“ID”上) 用户/项目Mysql 跨6个表查询,有更好的方法吗?,mysql,sql,Mysql,Sql,我所做的是,我希望每个用户都有自己的“唯一”编号系统。我没有将项目编号自动递增1,而是这样做的,Bob的第一个项目将从#1开始,Alice的编号也将从#1开始。房间和类别也是如此。我通过为项目、房间和类别创建“映射”表来实现这一点 下面的查询可以工作,但我知道它肯定可以重构。我在每个表中都有主键(在“ID”上) 用户/项目 | id | item_name | item_location |item_category | ------------------------------
| id | item_name | item_location |item_category |
--------------------------------------------------------
| 1 | item_a | 1 | 1 |
| 2 | item_b | 2 | 1 |
| 3 | item_c | 1 | 1 |
用户\地图\项目
| map_item_id | map_user_id | unique_item_id |
----------------------------------------------------
| 1 | 1 | 1 |
| 2 | 1 | 2 |
| 3 | 2 | 1 |
用户/客房
| id | room_name |
----------------------
| 1 | basement |
| 2 | kitchen |
| 3 | attic |
用户\地图\房间
| map_room_id | map_user_id | unique_room_id |
----------------------------------------------------
| 1 | 1 | 1 |
| 2 | 1 | 2 |
| 3 | 2 | 1 |
用户类别
| id | room_name |
----------------------
| 1 | antiques |
| 2 | appliance |
| 3 | sporting goods |
用户\地图\类别
| map_room_id | map_user_id | unique_category_id |
----------------------------------------------------
| 1 | 1 | 1 |
| 2 | 1 | 2 |
| 3 | 2 | 1 |
使用显式连接条件重写查询会使其更具可读性(同时执行相同的操作) 结果没有改变。查询计划应相同。我认为没有办法进一步改进查询
如果要在右表中找不到匹配行的结果中保留行,则应使用
LEFT[OUTER]JOIN
而不是[internal]JOIN
。在这种情况下,您可能希望将附加的WHERE
子句移动到JOIN
条件,因为它会更改结果。使用显式连接条件重写查询会使查询更具可读性(同时执行相同的操作)
结果没有改变。查询计划应相同。我认为没有办法进一步改进查询
如果要在右表中找不到匹配行的结果中保留行,则应使用
LEFT[OUTER]JOIN
而不是[internal]JOIN
。在这种情况下,您可能需要将附加的WHERE
子句移动到JOIN
条件,因为它会更改结果。您可以创建一个视图,并使用该视图使用该查询。这使您有机会在以后对其进行改进,而无需更改(视图)使用它的任何位置。这不是真正的解决方案,但希望是一个提示;)<代码>项目值不在您的表中?如果在联接表中找不到匹配的行,请声明要执行的操作。显示NULL
或从结果中删除行?我忽略了包含所有需要的字段,但项目信息来自users\u items表。您可以创建一个视图,并使用该视图使用该查询。这使您有机会在以后对其进行改进,而无需更改(视图)使用它的任何位置。这不是真正的解决方案,但希望是一个提示;)<代码>项目值不在您的表中?如果在联接表中找不到匹配的行,请声明要执行的操作。显示NULL
或从结果中删除行?我忽略了包含我需要的所有字段,但项目信息来自users\u items表。谢谢,users\u category
上的联接为什么不同于users\u room
?@luckytaxi:我使用此语法形式一次匹配两列。它与c.user\u id、=mc.map\u user\u id和c.category\u id=mc.map\u category\u id上的同义,但较短且(IMO)更清晰。换行符只是为了更好的可读性。这是有道理的,但是为什么在c.user\u id=mc.map\u user\u id上有,而在房间的映射表上没有?不管怎样,这个查询都很好,但我只是好奇。Thanks@luckytaxi:我从您的查询中收集了信息。我不知道你为什么以这种方式加入-你的数据模型和描述不完整。哈哈。。。我道歉,你是对的。我粘贴了该查询的旧版本。非常感谢您的帮助。谢谢,为什么users\u类别
上的连接与users\u room
不同?@luckytaxi:我使用此语法形式一次匹配两列。它与c.user\u id、=mc.map\u user\u id和c.category\u id=mc.map\u category\u id上的同义,但较短且(IMO)更清晰。换行符只是为了更好的可读性。这是有道理的,但是为什么在c.user\u id=mc.map\u user\u id上有,而在房间的映射表上没有?不管怎样,这个查询都很好,但我只是好奇。Thanks@luckytaxi:我从您的查询中收集了信息。我不知道你为什么以这种方式加入-你的数据模型和描述不完整。哈哈。。。我道歉,你是对的。我粘贴了该查询的旧版本。非常感谢你的帮助。
| map_room_id | map_user_id | unique_category_id |
----------------------------------------------------
| 1 | 1 | 1 |
| 2 | 1 | 2 |
| 3 | 2 | 1 |
SELECT mi.unique_item_id AS item_id
, i.item_name
, c.category_name
, i.item_value
, r.room_name
FROM users_map_item mi
JOIN users_items i ON i.id = mi.map_item_id
JOIN users_map_room mr ON mr.unique_room_id = i.item_location
JOIN users_room r ON r.room_id = mr.map_room_id
JOIN users_map_category mc ON mc.unique_category_id = i.item_category
JOIN users_category c ON (c.user_id, c.category_id)
= (mc.map_user_id, mc.map_category_id)
WHERE mr.map_user_id = 1
AND mc.map_user_id = 1
ORDER BY i.item_name