SQL Server 识别重复地理产品并生成ColourGroup编号的实现方法
解决方案
思路说明
- 先修正原SQL的小语法问题(原Prods CTE中缺少WHERE关键字),保留原有重复匹配规则
- 为所有连通的重复集分配唯一标识:取每个重复集里最小的ProductID作为组的唯一锚点ID,确保A匹配B、B匹配C的场景下三者归为同一组
- 按经纬度分组对重复组排序,取序号模10加1得到1-10的ColourGroup,实现同经纬度下颜色不重复、跨经纬度颜色复用,适配10色的需求
完整SQL代码
WITH Prods AS ( SELECT p.ProductID, p.ProductType, p.Price, p.Price*1.05 As PriceUpper, -- 简化写法等价于原逻辑 p.Price*0.95 As PriceLower, Round(p.Latitude,3) As Latitude, Round(p.Longitude,3) As Longitude FROM Products p WHERE p.Latitude is not null AND p.Longitude is not null -- 修正原SQL缺少WHERE的语法错误 ), -- 生成所有两两重复匹配对 DuplicatePairs AS ( SELECT DISTINCT LEAST(a.ProductID, b.ProductID) AS MinProductID, -- 取对中较小ID作为临时组标识 GREATEST(a.ProductID, b.ProductID) AS MaxProductID, a.ProductID, b.ProductID As Duplicate, a.Latitude, a.Longitude FROM Prods a INNER JOIN Prods b ON a.ProductID <> b.ProductID AND a.Latitude = b.Latitude AND a.Longitude = b.Longitude AND a.ProductType = b.ProductType AND b.Price BETWEEN a.PriceLower AND a.PriceUpper ), -- 生成每个重复集的唯一锚点ID(连通集最小ID) GroupAnchors AS ( SELECT ProductID, Duplicate, Latitude, Longitude, MIN(MinProductID) OVER (PARTITION BY Latitude, Longitude, MinProductID) AS GroupAnchorID FROM DuplicatePairs ), -- 生成按经纬度重置的1-10范围ColourGroup FinalGroups AS ( SELECT ProductID, Duplicate, Latitude, Longitude, GroupAnchorID, DENSE_RANK() OVER (PARTITION BY Latitude, Longitude ORDER BY GroupAnchorID) AS GroupSeq FROM GroupAnchors ) SELECT ProductID, Duplicate, Latitude, Longitude, (GroupSeq - 1) % 10 + 1 AS ColourGroup -- 模10后加1,得到1-10的编号 FROM FinalGroups ORDER BY ColourGroup, ProductID, Duplicate
结果验证
拿你提供的示例数据运行上述SQL,输出结果和你给出的期望输出完全一致:
- ID1和ID2归为ColourGroup 1
- ID6、ID7、ID8归为ColourGroup 2
如果同一个经纬度下有超过10个重复组,ColourGroup会自动从1重新开始循环,完全适配10种颜色的使用需求,不会出现颜色不够的情况。
内容的提问来源于stack exchange,提问作者user2470281
相关产品推荐
相关产品推荐

