【问题标题】:how to select rows with same column_a but different column_b?如何选择具有相同column_a但column_b不同的行?
【发布时间】:2019-10-28 13:09:36
【问题描述】:

我想在sql server中选择行,下面是我的问题:

Table1
-------------------------- 
|     Name   |    Type   |
--------------------------
|      A     |     1     |
|      A     |     2     |
|      B     |     1     |
|      B     |     3     |
|      A     |     3     |
|      C     |     1     |
|      C     |     3     |
|      D     |     1     |
|      D     |     2     |
|      D     |     3     |
|      .     |     .     |
|      .     |     .     |

选择如下行:

Table2
-------------------------- 
|     Name   |    Type   |
--------------------------
|      A     |     1     |
|      A     |     2     |
|      A     |     3     |
|      D     |     1     |
|      D     |     2     |
|      D     |     3     |
|      .     |     .     |
|      .     |     .     |

选择规则是……

显示名称和类型,其中类型必须有 1,2 和 3。

示例:A 有 1,2,3 种类型,所以我会选择它。

例子:B只有1,2个类型,所以我不会选择它。

【问题讨论】:

    标签: sql sql-server join case window-functions


    【解决方案1】:

    您可以为此使用窗口函数:

    select name, type
    from (
        select 
            t.*,
            sum(case when type in (1, 2, 3) then 1 else 0 end)
                    over(partition by name) cnt
        from mytable t
    ) t
    where cnt = 3
    

    这假设每个(名称,类型)元组在原始表中只出现一次,这与您的示例数据一致。

    Demo on DB Fiddle

    姓名 |类型 :--- | ---: 一个 | 1 一个 | 2 一个 | 3 D | 1 D | 2 D | 3

    【讨论】:

      【解决方案2】:

      您可以在三个 Type 列上使用 INNER JOINs 来实现此目的:

      SELECT Table1.[Name],
             Table1.[Type]
        FROM Table1
          INNER JOIN (
                     SELECT [Name]
                       FROM Table1
                       WHERE ([Type] = 1)
                     ) A ON A.[Name] = Table1.[Name]
          INNER JOIN (
                     SELECT [Name]
                       FROM Table1
                       WHERE ([Type] = 2)
                     ) B ON B.[Name] = A.[Name]
          INNER JOIN (
                     SELECT [Name]
                       FROM Table1
                       WHERE ([Type] = 3)
                     ) C ON C.[Name] = A.[Name]
      

      这个输出:

      Name    Type
      A       1
      A       2
      A       3
      D       1
      D       2
      D       3
      

      匹配的sqlfiddle

      这通过返回包含[Type] = 1 的行,然后只匹配[Type] = 2[Type] = 3 的行来工作。然后将其连接回您的主表并返回结果。

      【讨论】:

        【解决方案3】:

        获取带有group by name 的名称并在having 子句中设置条件:

        select * from Table1
        where name in (
          select name 
          from Table1
          group by name
          having count(distinct type) = 3
        )
        

        如果Type 列有除1, 2, 3 以外的其他值,则:

        select * from Table1
        where type in (1, 2, 3) and name in (
          select name 
          from Table1
          where type in (1, 2, 3)
          group by name
          having count(distinct type) = 3
        )
        

        请参阅demo

        结果:

        > Name | Type
        > :--- | ---:
        > A    |    1
        > A    |    2
        > A    |    3
        > D    |    1
        > D    |    2
        > D    |    3
        

        【讨论】:

          【解决方案4】:

          如果是 sql server 2017 及以上版本或 Azure SQL,则可以使用 string_agg,如下所示:

          Select * from #yourTable yt join (
              select [name], string_agg([Type], ',') as st_types
              from #YourTable 
              group by [name] ) a 
          on yt.name = a.[name] and a.st_types like '%1,2,3%'
          

          【讨论】:

            【解决方案5】:

            我给你这个,如果你有这将工作:

            A 1
            A 2
            A 3
            A 2
            

            它只会给你B。

            SELECT * 
            FROM Table1 
            WHERE Name in (
            SELECT Name from 
            (
               SELECT Name, Type, count(Name) c from Table1 where Type = 1
               GROUP BY Name, Type 
               HAVING count(Name) = 1
               UNION
               SELECT Name, Type, count(Name) c from Table1 where Type = 2
               GROUP by Name, Type 
               HAVING count(Name) = 1
               UNION
               SELECT Name, Type, count(Name) c from Table1 where Type = 3
               GROUP by Name, Type 
               HAVING  count(Name) = 1) t 
            GROUP by name
            HAVING count(c) = 3)
            

            这里是DEMO

            【讨论】:

            • @GMB 的解决方案也可以用更少的代码做到这一点:)
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2021-10-21
            • 1970-01-01
            • 2015-05-28
            • 2017-12-31
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多