加入多个(超过3个)表以及放置条件的位置的顺序是什么?

时间:2014-09-17 14:45:15

标签: mysql sql join where

我已经完成了相当多的阅读和测试,我可以从单个查询中获取我想要的信息,但我似乎无法加入它们以将所有内容都放在一个表中。

目标 - 列出包含相关块和AdminRole名称的所有容器。

这里是我需要的表格和字段之间关系的视觉效果: Table Structure Picture

由于我还无法附加图片,请参阅表格说明:

  • AdminACL
    • adminID(= adminrole_admin.adminID)(编辑:= adminrole.ID)
    • objectID(= Container.ID)
    • ObjectType(条件"容器")
  • adminrole_admin(编辑:不需要表格)
    • adminroleID(= adminrole.ID)
    • adminID(= AdminACL.adminID)
  • adminrole
    • ID(= adminrole_admin.adminroleID)(编辑:= AdminACL.adminid)
    • name< - 结果表中的所需字段[条件的奖励积分不像'隐藏_%']
  • 集装箱
    • ID(= AdminACL.objectID)
    • name< - 结果表中的所需字段
  • container_block
    • containerID(= Container.ID)
    • blockID(= Block.ID)
    • ID(= container_block.blockID)
    • name< - 结果表中的所需字段

我为每个部分都有选择语句,但由于它会产生异常混乱的查询,我尝试了连接,但最终得到了空集。我不确定从哪个表开始,如果我需要使用不同类型的连接和/或以不同的顺序。

这是我放弃之前尝试的最后一个查询:

SELECT C.name, B.name, A.name 
FROM container C
JOIN (SELECT adminid,objected from adminacl where objecttype='Container') ACL ON ACL.objectid=C.id
JOIN adminrole_admin AA ON ACL.adminid=AA.adminid
JOIN (select id,name from adminrole where name not like 'hidden_%') A ON AA.adminid=A.id
JOIN container_block CB ON C.id=CB.containerid
JOIN block B ON CB.blockid=B.id;

尽管我喜欢这个答案,但我也想了解如何在将来构建此类查询。我很确定我错过了一些明显的东西 - 只是很难将我所看到的所有其他例子都与之相关联。 TIA!

编辑:事实证明,adminacl.adminid = adminrole.id,这让事情变得更加简单。最后还需要隐藏'管理员角色,是在角色之上添加的基于特定用户的权限。根据Russ的回答,这就是我的最终查询最终结果:

SELECT container.name, block.name, adminrole.name
FROM block
    LEFT JOIN container_block ON container_block.blockid=block.id
    LEFT JOIN container ON container.id=container_block.containerid
    LEFT JOIN adminacl ON adminacl.objectid=container.id
    JOIN adminrole ON adminrole.id=adminacl.adminid
WHERE
    adminacl.objecttype='Container'
    AND block.blockstatus !=1 #to exclude unassigned blocks
ORDER BY container.name, block.name;

1 个答案:

答案 0 :(得分:0)

我喜欢从我真正想要的最大数量开始。从你的问题来看,我认为你想要一个包含容器和管理员角色的块列表,所以我从那里开始并在其他信息上加入左边,以创建列表。

SELECT Block.name, Container.name, adminrole.name from 
Block
    LEFT JOIN container_block ON container_block.containerid = Block.id
    LEFT JOIN Container ON Container.id = container_block.containerid
    LEFT JOIN AdminACL ON AdminACL.objectid = Container.id
    RIGHT JOIN adminrole_admin ON adminrole_admin.adminid #there could be multiple roles
    LEFT JOIN adminrole ON adminrole.id = adminrole_admin.adminroleID
WHERE 
    AdminACL.ObjectType = "Container"
    AND adminrole.name  not like 'hidden_%'; 
# shouldn't you have a `hidden` column on the table, instead of prefixing the name?

免责声明:我是从记忆中写下来的,甚至没有对任何东西进行测试,但试一试,它可能会让你走上正确的道路。

LEFT JOIN将排除未通过连接条件的行,因此您不应该获得大量不相关的空白,但我假设可以有很多管理员,所以我使用一个RIGHT JOIN,用于生成包含adminroleBlock的所有可能组合的行。这意味着同一个块会出现不同的管理员,并且相同的管理员将出现在多个块上。您的应用程序需要适当地处理此重复。