【问题标题】:what join is caused by "and"? [duplicate]什么联接是由“和”引起的? [复制]
【发布时间】:2013-03-21 18:49:54
【问题描述】:

我有一个包含以下表格的 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 是否真的在运行两个选择并加入结果,可能是按行号?

【问题讨论】:

  • 可能重复的问题是相关的,但远非完全重复。

标签: sql localdb


【解决方案1】:

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

SELECT UserId, RoleID
FROM UserProfile, webpages_Roles 

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

在您的情况下,这又是一个现实(如 DiscoInfiltrator 的回答所示),

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

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

希望这可以澄清,干杯

【讨论】:

    【解决方案2】:

    当您执行此查询时:

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

    你正在做一个cross join。您应该养成对交叉连接进行具体说明的习惯,并使用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
    

    在执行cross join 时,您正在创建一个笛卡尔积——第一个表中的每一行都与另一个表中的所有行匹配。然后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
    

    【讨论】:

    • "where 子句是这个结果集的过滤器。"这就是我所缺少的。
    【解决方案3】:

    当您从多个表中进行选择时,实际上是在隐式连接这些表。

    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”的行。

    【讨论】:

      猜你喜欢
      • 2014-12-18
      • 2012-09-18
      • 1970-01-01
      • 2013-06-09
      • 2021-12-13
      • 2011-04-24
      • 2012-04-16
      • 1970-01-01
      • 2023-03-04
      相关资源
      最近更新 更多