equi连接长数据结构

时间:2012-06-10 18:54:12

标签: sql oracle

我有一堆表,下面是表列表:

  • System_User
  • Acc_Roles
  • Acc_User_role_map
  • Acc_Permission
  • Acc_Role_Permission_Map
  • Acc_Menu_Items
  • Acc_SubMenu
  • Acc_Menu

我将解释上面的表格字段和关系。

我的查询就在这里:

select acc_menu_items.* from acc_menu, acc_menu_items, acc_submenu, system_user, acc_user_role_map, acc_roles, acc_role_permission_map, acc_permission
where system_user.user_id=acc_user_role_map.user_id
and acc_user_role_map.ROLE_ID=acc_roles.id
and acc_roles.id=acc_role_permission_map.ROLE_ID
and acc_role_permission_map.PERMISSION_ID=acc_permission.id

and acc_permission.MENUITEM_ID=acc_menu_items.id
and acc_menu_items.menu_id=acc_menu.id

and acc_menu_items.SUBMENU_ID=acc_submenu.id

and system_user.USER_ID='userName' and acc_menu.menu_name='menuName';

我的问题是当我运行上面的查询时显示为空。

在该查询中删除表名“acc_submenu”和“acc_menu_items.SUBMENU_ID = acc_submenu.id”

我收到数据很好,如果我把子菜单列表也变空了。

如果有什么不清楚,我会上传完整的数据。

任何人都有任何想法?

被修改

找到下面的图片链接

http://www.4shared.com/photo/2Ml256my/Untitled-1-copy.html

我的查询是:

select acc_menu_items.* from acc_menu, acc_menu_items, acc_submenu, system_user, acc_user_role_map, acc_roles, acc_role_permission_map, acc_permission
where system_user.user_id=acc_user_role_map.user_id
and acc_user_role_map.ROLE_ID=acc_roles.id
and acc_roles.id=acc_role_permission_map.ROLE_ID
and acc_role_permission_map.PERMISSION_ID=acc_permission.id

and acc_permission.MENUITEM_ID=acc_menu_items.id
and acc_menu_items.menu_id=acc_menu.id

and system_user.USER_ID='setupadmin' and acc_menu.menu_name='Administrator';

上面的查询是获取数据,当我用'MainMenu'替换'Administrator'时,它不起作用,请解释一下是什么问题?

我该怎么办?有什么想法吗?

2 个答案:

答案 0 :(得分:2)

使用显式连接语法的第二个查询:

select ami.* 
  from acc_submenu
    -- MISSING JOIN CONDITION
  join acc_roles ar
    -- MISSING JOIN CONDITION
  join acc_user_role_map aurm
    on aurm.role_id = ar.id
  join system_user su
    on su.user_id = aurm.user_id
  join acc_role_permission_map arpm
    on ar.id = arpm.role_id
  join acc_permission ap
    on arpm.permission_id = ap.id
  join acc_menu_items ami
    on ap.menuitem_id = ami.id
  join acc_menu am
    on ami.menu_id = am.id
 where su.user_id = 'setupadmin' 
   and am.menu_name = 'Administrator'

正如您所看到的,您有一些缺失的加入条件,这意味着您正在acc_submenuacc_roles上进行Cartesian join。我认为这是无意的......

使用显式连接语法的第一个查询:

select ami.* 
  from system_user su
  join acc_user_role_map aurm
    on su.user_id = aurm.user_id
  join acc_roles ar 
    on aurm.role_id = ar.id
  join acc_role_permission_map arpm
    on ar.id = arpm.role_id
  join acc_permission ap
    on arpm.permission_id = ap.id
  join acc_menu_items ami
    on ap.menuitem_id = ami.id
  join acc_menu am
    on ami.menu_id = am.id
  join acc_submenu as
    on ami.submenu_id = as.id
 where su.user_id = 'userName' 
   and am.menu_name = 'menuName';

这一切似乎都过于复杂。如果我们使用您发布的数据向后工作;你想要acc_menu_items

所在的menu_name = 'MainMenu'表中的所有内容

那将是:

select ami.*
  from acc_menu am
  join acc_menu_items ami
    on am.id = ami.menu_id

你也想把它限制在system_user.user_id = 'setupadmin',这对我来说是不幸的,因为我现在要写很多东西......顺便说一下,没有真正的理由去system_user,除非你希望所有事情都在name = 'pradeep'

在我得到的时候建立一个联接:

select ami.*
  from acc_user_role_map aurm
  join acc_role_permission_map arpm
    on aurm.role_id = arpm.role_id
  join acc_permission ap
    on arpm.permission_id = ap.id
    -- Now I'm stuck as there-s nothing else to join to
    -- however, for the sake of argument let-s assume that acc_permission
    -- does have menuitem_id and that that number is one of those
    -- specified
  join acc_menu_items ami
    on ap.menuitem_id = ami.id
  join acc_submenu as
    on ami.submenu_id = as.id
  join acc_menu am
    on am.id = as.menu_id
 where aurm.user_id = 'setupadmin'
   and am.menu_name = 'MainMenu'

正如您所看到的,连接较少,这使得它更清晰。还有一个假设我无法验证。我假设在menuitem_id中存在acc_permission的1123,1125,1127或1129。

但是还有另一个微妙的区别。我首先加入acc_submenu 然后加入acc_menu以获取查询。这也改变了连接条件;这不再是:

on acc_menu_items.menu_id = acc_menu.id

on acc_menu.id = acc_submenu.menu_id

这就是你没有得到结果的原因;您的加入查询不正确。


这引出了我几点:

  • 由于您的第二个查询演示使用显式连接语法是一种容易出错的方法。 不值得使用隐式连接语法;特别是当您的查询有很多连接或复杂时。几十年来它们一直是SQL标准,所以你应该使用它们。

  • 创建复杂查询时,如果一次构建一层,通常会更容易。这意味着您可以验证在每个阶段是否返回了您期望的结果。如果出错,您可以轻松查明发生的位置。

还有一些友好的建议,你可以随意忽略或不遵守:

您的架构过于复杂;特别是在菜单表周围。特别令人不安的是acc_menu_items之后的联接必须是两个不同表中的一个,你不知道哪个。如果可以简化这个,请做。例如,通过向parent_id添加acc_menu并在此处移动子菜单。然后,您可以删除acc_menu_items上的额外列。

进一步阅读:

答案 1 :(得分:0)

没有太多想法:你的线阅读

and acc_menu_items.SUBMENU_ID=acc_submenu.id

表示acc_menu_items.SubMenu_ID在Acc_submenu.id中有相应的条目。你有支持该断言的数据吗?

含义:在ACC_MENU_ITEMS.SubMenu_ID中,您有一条名为“1”的记录 在Acc_SubMenu.id中你也有一个相同数据类型的记录,如果没有,那么你的逻辑是否有缺陷。根据你的测试,这可能是问题