【问题标题】:"Where IN" with multiple columns (SQL Server)具有多列的“在哪里”(SQL Server)
【发布时间】:2009-01-12 13:40:37
【问题描述】:

我使用的是 SQL Server 2005。

查询如下所示

Select col1, col2, col3 from <subquery> where (col1,col2) in <subquery>

SQL Server 似乎不喜欢这样。任何人都知道的实现方式不涉及转换为 varchars 或其他任何混乱的东西?

这是实际的查询。

SELECT * 
FROM         
 (
    SELECT NEWID() AS guid, UserID, RoleId, ClubId, 0 AS GroupRole
    FROM dbo.Portal_UserRoles

    UNION

    SELECT NEWID() AS guid, dbo.Portal_UserGroups.UserId, 
           dbo.Portal_GroupRoles.RoleId, dbo.Portal_UserGroups.ClubId, 
           dbo.Portal_GroupRoles.GroupId AS GroupRole
    FROM dbo.Portal_GroupRoles 
    INNER JOIN dbo.Portal_UserGroups 
        ON dbo.Portal_GroupRoles.GroupId = dbo.Portal_UserGroups.GroupId
  ) AS derivedtbl_1
WHERE (derivedtbl_1.RoleId,derivedtbl_1.ClubId) IN 
      (
         SELECT Portal_GroupRoles.RoleId, Portal_ClubGroups.ClubId
         FROM Portal_GroupRoles 
         INNER JOIN Portal_ClubGroups
             ON Portal_GroupRoles.GroupId = Portal_ClubGroups.GroupId
      )

【问题讨论】:

  • 如果您将其格式化为更具可读性,它会帮助人们帮助您。
  • 抱歉,不知道该怎么做。
  • 很奇怪,这个问题已经获得了将近 3k 的浏览量,却没有一个支持。

标签: sql sql-server sql-server-2005


【解决方案1】:

执行您所寻求的标准的经典方法是 EXISTS 子句:

SELECT * 
    FROM         
    (
        SELECT NEWID() AS guid, UserID, RoleId, ClubId, 0 AS GroupRole
        FROM dbo.Portal_UserRoles

        UNION

        SELECT NEWID() AS guid, dbo.Portal_UserGroups.UserId, 
               dbo.Portal_GroupRoles.RoleId, dbo.Portal_UserGroups.ClubId, 
               dbo.Portal_GroupRoles.GroupId AS GroupRole
            FROM dbo.Portal_GroupRoles 
                 INNER JOIN dbo.Portal_UserGroups 
                 ON dbo.Portal_GroupRoles.GroupId = dbo.Portal_UserGroups.GroupId
    ) AS derivedtbl_1
WHERE EXISTS
  (
     SELECT Portal_GroupRoles.RoleId, Portal_ClubGroups.ClubId
         FROM (Portal_GroupRoles 
               INNER JOIN Portal_ClubGroups
               ON Portal_GroupRoles.GroupId = Portal_ClubGroups.GroupId) AS cgr
         WHERE derivedtbl_1.RoleID = cgr.RoleId
           AND derivedtbl_1.ClubId = cgr.ClubId
  )

小心将两列条件分成两个单独的 IN 子句;它不会给你与在一个 EXISTS 子句中应用两列条件相同的答案(通常)。

【讨论】:

    【解决方案2】:

    在派生表上进行连接,而不是使用in

    SELECT * 
    FROM  
      (
        SELECT NEWID() AS guid, UserID, RoleId, ClubId, 0 AS GroupRole 
        FROM dbo.Portal_UserRoles 
    
        UNION 
    
        SELECT NEWID() AS guid, dbo.Portal_UserGroups.UserId, 
               dbo.Portal_GroupRoles.RoleId, dbo.Portal_UserGroups.ClubId,
               dbo.Portal_GroupRoles.GroupId AS GroupRole 
        FROM dbo.Portal_GroupRoles 
        INNER JOIN dbo.Portal_UserGroups 
            ON dbo.Portal_GroupRoles.GroupId = dbo.Portal_UserGroups.GroupId
      ) AS derivedtbl_1 
    
    INNER JOIN 
      (
        SELECT Portal_GroupRoles.RoleId, Portal_ClubGroups.ClubId 
        FROM Portal_GroupRoles 
        INNER JOIN Portal_ClubGroups 
            ON Portal_GroupRoles.GroupId = Portal_ClubGroups.GroupId
      ) derivedtbl_2
        ON derivedtbl_1.RoleID = derivedtbl_2.RoleID 
          AND derivedtbl_1.ClubId = derivedtbl_2.ClubId
    

    【讨论】:

    • 不幸的是,我需要一个 where 子句。真的我应该发布这个,但它应该看起来像 Select col1, col2, col3 from (subquery) where (col1,col2) in (subquery) OR col2 IS Null, will not work with a join.
    【解决方案3】:
    SELECT 
        /*      
        your selected fields, joins here
        */
    WHERE -- (derivedtbl_1.RoleId,derivedtbl_1.ClubId) IN 
        EXISTS
        (
            -- actually you can change these two fields to * (asterisk ) or 1, whatever, even your name, what matters only is the testing of existence(see below)
            SELECT Portal_GroupRoles.RoleId, Portal_ClubGroups.ClubId 
            FROM Portal_GroupRoles 
            INNER JOIN Portal_ClubGroups
            ON Portal_GroupRoles.GroupId = Portal_ClubGroups.GroupId
    
            -- here is your IN (the testing of existence):
            WHERE Portal_GroupRoles.RoleId = derivedtbl_1.RoleId AND 
            AND derivedtbl_1.ClubId = derivedtbl_1.ClubId
          )
    
    alternatively:
    
    SELECT 
        /*      
        your selected fields, joins here
        */
    JOIN 
        (
            SELECT Portal_GroupRoles.RoleId, Portal_ClubGroups.ClubId
            FROM Portal_GroupRoles 
            INNER JOIN Portal_ClubGroups
            ON Portal_GroupRoles.GroupId = Portal_ClubGroups.GroupId
        ) X 
        -- here is your IN:
        ON X.RoleId = derivedtbl_1.RoleId
        AND X.ClubId = derivedtbl_1.ClubId
    

    【讨论】:

      【解决方案4】:

      您的语法很有用,并且在标准 SQL 中受支持。它尚未在 SQL Server 中实现,但您可以投票支持它的包含 here

      【讨论】:

      • onedaywhen 如果您从 Oracle 背景进入 sql server 环境,则提供了最佳答案。简单的答案是还没有。有时即使您有一个规范化的数据库,这也是一个有用的查询。 SQL标准?什么 SQL 标准?我赞赏 postgresql 预先警告您他们是否遵循标准,或者他们是否正在实施标准的扩展。
      【解决方案5】:

      你必须在两个子句中分开

       where col1 in (...) AND col2 in (...)
      

      或者你可以稍微重构一下

      select * FROM (
           SELECT NEWID() AS guid, UserID, RoleId, ClubId, 0 AS GroupRole FROM dbo.Portal_UserRoles 
           UNION 
           SELECT NEWID() AS guid, dbo.Portal_UserGroups.UserId, dbo.Portal_GroupRoles.RoleId, dbo.Portal_UserGroups.ClubId, dbo.Portal_GroupRoles.GroupId AS GroupRoles FROM dbo.Portal_GroupRoles INNER JOIN dbo.Portal_UserGroups ON dbo.Portal_GroupRoles.GroupId = dbo.Portal_UserGroups.GroupId) 
           AS derivedtbl_1, Portal_GroupRoles, Portal_ClubGroup
      where derivedtbl_1.RoleId = Portal_GroupRoles.RoleId
      and derivedtbl_1.ClubId = Portal_ClubGroups.ClubId
      and Portal_GroupRoles.GroupId = Portal_ClubGroups.GroupId
      

      【讨论】:

      • 两次执行相同的查询似乎有点过分
      • 干得好,但我不知道“AS derivedtbl_1,Portal_GroupRoles,Portal_ClubGroup”是如何工作的。有链接或名称吗?
      • 这不是一个好的答案:它无法处理 col1 和 col2 同时匹配同一单行的要求,并且如果 col1 匹配任何 1 行并且 col2 匹配任何 1 行,则允许它匹配。
      • 它被称为“我老了,在它有 JOIN 关键字之前就开始使用 MSSQL”:) 说真的:这是一种不同的连接方式,你在 FROM 子句中添加表并创建加入 WHERE 子句
      • @Eduardo:我可以不使用连接;我在连接符号存在之前就学习了 SQL。我暂时撤回了我的反对票,因为长查询并没有像关于两个 IN 子句的简短评论所暗示的那样。不过,这个建议是完全错误的。请删除它,只留下 OK 位。
      猜你喜欢
      • 2010-10-02
      • 1970-01-01
      • 1970-01-01
      • 2011-11-12
      • 1970-01-01
      • 2010-10-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多