代码之家  ›  专栏  ›  技术社区  ›  Adam R. Grey

什么联接是由“和”引起的?[副本]

  •  0
  • Adam R. Grey  · 技术社区  · 11 年前

    我有一个localDB数据库,其中包括以下表格:

    UserProfile,其中包含:

    UserId  UserName
    1           Adam
    

    webpages_Roles,其中包含:

    RoleID RoleName
    1      user
    2      admin
    

    webpages_UsersInRoles,它有两列(UserId和RoleId),并且为空。

    我想要一个按名称将用户添加到按名称的角色中的查询。 以确定要插入的内容,如果我运行:

    SELECT UserId, RoleID 
    FROM UserProfile, webpages_Roles 
    WHERE UserProfile.UserName = 'Adam' 
       OR webpages_roles.RoleName = 'admin';
    

    我明白了:

    UserId  RoleId
    1       2
    1       1
    

    这是有道理的;这是交叉连接。但我基本上只想同时运行两个单独的选择,并将它们粘在一起。我试过了:

    SELECT UserId, RoleID 
    FROM UserProfile, webpages_Roles 
    WHERE UserProfile.UserName = 'Adam' 
      AND webpages_roles.RoleName = 'admin';
    

    它奏效了;我得到了UserId 1和RoleId 2。但我不理解“和”;这不是像把苹果比作桔子吗?这不应该是语法错误吗?localDB是否真的在运行两个选择并连接结果,也许是通过行号?

    3 回复  |  直到 11 年前
        1
  •  4
  •   Gordon Linoff    11 年前

    执行此查询时:

    SELECT UserId, RoleID 
    FROM UserProfile, webpages_Roles
    WHERE UserProfile.UserName = 'Adam' AND webpages_roles.RoleName = 'admin';
    

    你正在做一个 cross join 。你应该养成对交叉连接具体化的习惯,并使用 交叉连接 而不是 , 在任何情况下,这相当于:

    SELECT UserId, RoleID
    FROM (select u.*
          from UserProfile u
          where u.UserName = 'Adam'
         ) cross join
         (select w.*
          from webpages_Roles w
          WHERE w.RoleName = 'admin'
         ) w
    

    当做 交叉连接 您正在创建一个笛卡尔乘积——第一个表中的每一行都与另一个表中所有的行相匹配。这个 where 子句则是该结果集的筛选器。

    如果你想对齐数据,那就更难了。以下是一种使用SQL Server语法的方法:

    SELECT UserId, RoleID
    FROM (select u.*, row_number() over (order by (select NULL)) as seqnum
          from UserProfile u
          where u.UserName = 'Adam'
         ) u join
         (select w.*, row_number() over (order by (select NULL)) as seqnum
          from webpages_Roles w
          WHERE w.RoleName = 'admin'
         ) w
         on u.seqnum = w.seqnum
    
        2
  •  2
  •   DiscoInfiltrator    11 年前

    无论何时从多个表中进行选择,实际上都是在隐式地连接这些表。

    SELECT UserId, RoleID 
    FROM UserProfile, webpages_Roles; 
    

    上面的查询将返回如下内容:

    UserId  UserName  RoleID RoleName
    1           Adam  1      user
    1           Adam  2      admin
    

    因此,当您添加where子句时:

    SELECT UserId, RoleID 
    FROM UserProfile, webpages_Roles 
    WHERE UserProfile.UserName = 'Adam' AND webpages_roles.RoleName = 'admin';
    

    它只返回UserProfile.Username为“Adam”且webpages_roles.RoleName为“admin”的行。

        3
  •  1
  •   Carlos    11 年前

    这是正确的,而不是任何类型的错误的原因如下。 当你这样做的时候

    SELECT UserId, RoleID
    FROM UserProfile, webpages_Roles 
    

    没有 WHERE 子句,您在标准SQL中得到的是关系的笛卡尔乘积,即, UserProfile x webpages_Roles

    这反过来又是一种现实,在你的情况下(如DiscoInfiltator的回答所示),

    UserId  UserName  RoleID RoleName
    1           Adam  1      user
    1           Adam  2      admin
    

    这意味着查询的这一部分 WHERE UserProfile.UserName = 'Adam' AND webpages_roles.RoleName = 'admin'; 作用于包含UserName和RoleName属性两者的关系,

    希望这能澄清,欢呼