SQL 服务器找到包含的组
SQL Server find contained groups
我正在尝试 select 仅包含其他组中未包含的组。
在此示例中,组号 2 包含在组号 1 中,因为组号 1 具有组号 2 的所有值。
组号 3 不包含在组号 1 中,因为它具有组号 1 不包含的值 50。
结果应该是第 1 组和第 3 组。
(或者相反——只获取包含在其他组中的组号 2)
寻找一种不循环的方法,因为我有超过 200 万个值。
我的 table 看起来像这样:
group_number id
-------------------
1 10
1 20
1 30
1 40
2 10
2 40
3 10
3 30
3 50
我已经使用您提供的数据集进行了测试并且有效。
第一个,不包含在另一个组中的组:
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 , 找到相同数量的 ID。
您可以尝试以下查询。
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
我已经通过计数逻辑得出了你的逻辑。
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
希望对您有所帮助。
每个组号代表一个集合,您想检查给定的集合是否是另一个集合的子集。您可以将 table 与自身连接起来,以将每个集合与所有其他集合相匹配,并使用 left join + count 来确定 A 是否是 B[ 的子集=20=](组 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)
以上 returns 组 ID 是另一个组的子集(在您的示例中为 2)。在 NOT IN
中使用上面的内容来获取非子集组 ID。
我正在尝试 select 仅包含其他组中未包含的组。
在此示例中,组号 2 包含在组号 1 中,因为组号 1 具有组号 2 的所有值。
组号 3 不包含在组号 1 中,因为它具有组号 1 不包含的值 50。
结果应该是第 1 组和第 3 组。
(或者相反——只获取包含在其他组中的组号 2)
寻找一种不循环的方法,因为我有超过 200 万个值。
我的 table 看起来像这样:
group_number id
-------------------
1 10
1 20
1 30
1 40
2 10
2 40
3 10
3 30
3 50
我已经使用您提供的数据集进行了测试并且有效。 第一个,不包含在另一个组中的组:
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 , 找到相同数量的 ID。
您可以尝试以下查询。
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
我已经通过计数逻辑得出了你的逻辑。
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
希望对您有所帮助。
每个组号代表一个集合,您想检查给定的集合是否是另一个集合的子集。您可以将 table 与自身连接起来,以将每个集合与所有其他集合相匹配,并使用 left join + count 来确定 A 是否是 B[ 的子集=20=](组 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)
以上 returns 组 ID 是另一个组的子集(在您的示例中为 2)。在 NOT IN
中使用上面的内容来获取非子集组 ID。