mysql - 如何在 SQL 中确定等效分组(递归)?
问题描述
我有一个由他们的 SKU 标识的产品列表。为简化起见,我在这里将它们命名为 A、B、C、D、...。默认情况下,这些 SKU 中的每一个都被分配了一个已经存在的GroupID
,为简单起见,我在这里将它们编号为 1、2、3、...。
这同样GroupID
意味着“这些 SKU 是等效的,因此可以使用/购买其中任何一个,因为它没有区别”。
问题是,一些 SKU 出现不止一次,因为它们来自不同的购买来源,但由于它们来自不同的来源,它们有不同的分组。
因此,目标是合并分组并确保它们具有相同的分组。
如果我的插图可能不是超级漂亮,我已经道歉,但我正在努力。这是一个关于原始数据的小数据表示例(第一行是列名):
Source SKU GroupID
Seller1 A 1
Seller1 B 1
Seller1 C 1
Seller2 B 2
Seller2 D 2
Seller2 E 2
Seller3 A 3
Seller3 B 3
Seller4 F 4
Seller4 G 4
Seller4 H 4
结果应该是这样的:
Source SKU GroupID
Seller1 A 1
Seller1 B 1
Seller1 C 1
Seller2 B 1
Seller2 D 1
Seller2 E 1
Seller3 A 1
Seller3 B 1
Seller4 F 4
Seller4 G 4
Seller4 H 4
基本上,如果Any SKU in GroupID X is a subset of GroupID Y, then GroupID Y = GroupID X
. 但这应该适用于所有 GroupID,因此它似乎是递归的。
我希望我可以展示我已经尝试过并且已经尝试了几天的代码,但实际上我只设法产生了垃圾。
在 C# 中,我知道如何处理这个问题,但我似乎无法完全理解 SQL,因为我没有那么有经验,不幸的是我需要在 SQL 中使用它。
我会感谢任何形式的帮助,即使这只是你们建议我应该尝试的提示或方向。非常感谢!
解决方案
您需要组之间的对应关系,可以使用递归 CTE 进行计算:
with recursive tt as (
select distinct t1.groupid as groupid1, t2.groupid as groupid2
from t t1 join
t t2
on t1.sku = t2.sku
),
cte as (
select tt.groupid1, tt.groupid2, concat_ws(',', tt.groupid1, tt.groupid2) as visited
from tt
union all
select cte.groupid1, tt.groupid2, concat_ws(',', visited, tt.groupid2)
from cte join
tt
on cte.groupid2 = tt.groupid1
where find_in_set(tt.groupid2, cte.visited) = 0
)
select groupid1, min(groupid2) as overall_group
from cte
group by groupid1;
然后,您可以将其加入原始表以获得“整体组”:
with recursive tt as (
select distinct t1.groupid as groupid1, t2.groupid as groupid2
from t t1 join
t t2
on t1.sku = t2.sku
),
cte as (
select tt.groupid1, tt.groupid2, concat_ws(',', tt.groupid1, tt.groupid2) as visited
from tt
union all
select cte.groupid1, tt.groupid2, concat_ws(',', visited, tt.groupid2)
from cte join
tt
on cte.groupid2 = tt.groupid1
where find_in_set(tt.groupid2, cte.visited) = 0
)
select t.*, g.overall_group
from t join
(select groupid1, min(groupid2) as overall_group
from cte
group by groupid1
) g
on t.groupid = g.groupid1;
这是一个 db<>fiddle。
注意:您的示例数据相当“完整”,因此您不需要针对该特定数据使用递归 CTE。但是,我猜您的真实组的重叠较少,在这种情况下递归是必要的。
推荐阅读
- web - 如何将我的移动应用程序链接到我的新网站?
- java - 如果我们在 Spring MVC 中组合类,我该如何设置 id?
- javascript - 数组列表按布尔值排序,然后按日期 JavaScript / TypeScript
- networking - 在浏览器或 wget 命令中访问 gitlab 服务器 url 时出现错误 ERR_EMPTY_RESPONSE
- javascript - 过滤来自登录请求的响应以删除标头和配置数据
- sql-server - 在 Visual Studio 的数据源中键入地址
- javascript - 重新运行 const 声明的函数的最佳方法是什么?
- wordpress - 无法为 Wordpress 设置联系表格 7 的样式
- r - R中表格值之间的3D插值
- react-native - 如何修复“RealmObject 不能作为函数调用”realm-js 错误?