【问题标题】:SQL Server find contained groupsSQL Server 查找包含的组
【发布时间】:2019-05-24 15:40:16
【问题描述】:

我正在尝试仅选择不包含在其他组中的组。

在此示例中,组 2 包含在组 1 中,因为组 1 具有组 2 的所有值。

组号 3 不包含在组号 1 中,因为它具有组号 1 不包含的值 50。

结果应该是第 1 组和第 3 组。

(或相反-仅获取包含在其他组中的组号 2)

寻找一种不循环的方式,因为我有超过 200 万个值。

我的桌子是这样的:

group_number    id
-------------------    
1               10
1               20
1               30
1               40
2               10
2               40
3               10
3               30
3               50

【问题讨论】:

    标签: sql sql-server contains


    【解决方案1】:

    我已经使用您提供的数据集进行了测试,并且可以正常工作。 第一个,不包含在另一个组中的组:

    SELECT DISTINCT Group_Number FROM #T
        WHERE NOT EXISTS (SELECT Group_Number G2 
                        FROM #T AS T2 
                        WHERE T2.Group_Number <> #t.Group_Number
                          AND T2.ID = #T.ID)
    

    而且...另一种方法很容易拥有这个:

    SELECT DISTINCT Group_Number FROM #T WHERE NOT Group_Number IN (
      SELECT DISTINCT Group_Number FROM #T
        WHERE NOT EXISTS (SELECT Group_Number G2 
                        FROM #T AS T2 
                        WHERE T2.Group_Number <> #t.Group_Number
                          AND T2.ID = #T.ID)
      )
    

    只是问自己,我意识到我的回答并不完全准确。 首先,我意识到添加:

    INSERT INTO #t 
    VALUES (6, 50),
        (7, 60),
        (8, 50),
        (8, 60)
    

    第 8 组没有出现,因为其中一项出现在第 6 组中,而另一项出现在第 7 组中。 所以,我做了很多检查,得出的结论是,下面的代码是保证结果的代码,也提供了可追溯性来验证响应是否正确:

    SELECT DISTINCT Group_Number FROM 
        (
        SELECT T1.Group_Number, T1.Rows, T2.Group_Number as Comparing_With_Other_Group, Count(DISTINCT T2.ID) AS Rows_On_Other_Group
            FROM (
                SELECT Group_Number, Count(DISTINCT ID) AS Rows 
                    FROM #T
                    GROUP BY Group_Number
            ) T1
            INNER JOIN #T AS T2
                ON T1.Group_Number <> T2.Group_Number
                AND EXISTS (SELECT 1 FROM #T WHERE #T.Group_Number = T1.Group_Number and #T.ID = T2.ID)
            GROUP BY T1.Group_Number, T2.Group_Number, T1.Rows
        ) SubQry
        WHERE Rows = Rows_On_Other_Group
    

    如果您仅运行 SubQry,您将看到可追溯性,而完整查询将向您显示系统可以找到另一个组的组,该组过滤我正在搜索的组中的 ID,找到相同数量的身份证。

    【讨论】:

      【解决方案2】:

      您可以尝试以下查询。

      SELECT DISTINCT Group_Number FROM #temp
          WHERE NOT EXISTS (SELECT DISTINCT Group_Number G2 
                          FROM #temp AS T2 
                          WHERE T2.Group_Number <> #temp.Group_Number
                            AND T2.ID = #temp.ID)
      

      输出是-

      Group_Number
      1
      3
      

      Demo

      【讨论】:

        【解决方案3】:

        我已经使用计数逻辑达到了你的逻辑。

           create table grp(a int ,b int)
        
           insert into grp
        
           select 1,10 union
           select 1,20 union
           select 1,30  union
           select 1,40  union
           select 2,10  union
           select 2,40  union
           select 3,10  union
           select 3,30  union
           select 3,50
        
        
        
           drop table #temo
           select distinct b.a as d ,b.b as g into #temo
           from grp a inner join grp b on (a.a<>b.a and a.b=b.b)
           where a.a <> b.a
        
        
           select a from grp
           except
           select a.d from (
           select d,count(tt) as cnt from (
           select d,g,row_number() over (partition by d  order by d)  tt from 
           #temo
           )rr
           group by d) a inner join (select a,count(a) as cnt from grp
           group by a) b on a.d=b.a and a.cnt=b.cnt
        

        希望这会有所帮助。

        【讨论】:

          【解决方案4】:

          每个组号代表一个集合,您要检查给定集合是否是另一个集合的子集。您可以将表与自身连接以将每个集合与所有其他集合匹配,并使用左连接 + 计数来确定 A 是否是 B 的子集(组中的每一行 A 在组 B 中有匹配的行):

          SELECT a.group_number
          FROM t AS a
          INNER JOIN (
              SELECT DISTINCT group_number
              FROM t
          ) AS x ON x.group_number <> a.group_number
          LEFT JOIN t AS b ON b.group_number = x.group_number AND b.id = a.id
          GROUP BY a.group_number, x.group_number
          HAVING COUNT(a.id) = COUNT(b.id)
          

          以上返回的组 ID 是另一个组的子集(在您的示例中为 2)。在 NOT IN 中使用上述内容来获取非子集组 ID。

          【讨论】:

            猜你喜欢
            • 2018-04-18
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-10-29
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多