Mysql 跨6个表查询,有更好的方法吗?

Mysql 跨6个表查询,有更好的方法吗?,mysql,sql,Mysql,Sql,我所做的是,我希望每个用户都有自己的“唯一”编号系统。我没有将项目编号自动递增1,而是这样做的,Bob的第一个项目将从#1开始,Alice的编号也将从#1开始。房间和类别也是如此。我通过为项目、房间和类别创建“映射”表来实现这一点 下面的查询可以工作,但我知道它肯定可以重构。我在每个表中都有主键(在“ID”上) 用户/项目 | id | item_name | item_location |item_category | ------------------------------

我所做的是,我希望每个用户都有自己的“唯一”编号系统。我没有将项目编号自动递增1,而是这样做的,Bob的第一个项目将从#1开始,Alice的编号也将从#1开始。房间和类别也是如此。我通过为项目、房间和类别创建“映射”表来实现这一点

下面的查询可以工作,但我知道它肯定可以重构。我在每个表中都有主键(在“ID”上)

用户/项目

|  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