2016-03-06 54 views
0

我想弄清楚如何根据几个不同的列和表找到重复项。在几个列和表上查找重复条目

我有这些表:

  • 产品
  • 标签(列表标签识别和产品ID - 每个标签一行)
  • 组(名单groupId和产品ID - 一个每GROUPID行)

我想在我的餐桌产品列productName,brandid,origin上找到完全匹配。但是为了将行重复投放,我还需要进行比较,以便分配完全相同的标签(列:tagid)和组(列:groupid)。

每个产品可能有多个标签和多个组。

这就是我想到的......但它并不完全符合我的需要。

SQLFiddle http://sqlfiddle.com/#!9/43f19/1

在我的SQL小提琴比如我列出了10种不同的产品。

例如,产品1,2是完全匹配的,因此应列为重复。 产品编号3只有一个组分配,因此即使其他参数适合(不应列出),也与产品1和2不同。我与dupid专栏的意图是列出一组重复的第一个条目。

id | name | brandid | origin | tags | groups | dupid 
1 | prod |  1  | England | 1,2  | 1,2  |  1  
2 | prod |  1  | England | 1,2  | 1,2  |  1 
3 | prod |  1  | England | 1,2  |  1  |  3 

应该被列为我的SQL小提琴精确匹配成套工程项目有:

id 1 
id 2 
id 4 
id 5 

我的猜测,为什么失败是我还没有成功的标签和组正确参与进入我的比较。

SELECT m.*,dup.id AS dupid,GROUP_CONCAT(DISTINCT t.tagid ORDER BY t.tagid ASC) AS alltags,GROUP_CONCAT(DISTINCT g.groupid ORDER BY g.groupid ASC) AS groups 
FROM `products` m 
JOIN (SELECT id,`productName`, brandid, origin, COUNT(*) AS c FROM products 
GROUP BY `productName`, brandid, origin HAVING c > 1) dup ON m.`productName` = dup.`productName` AND m.brandid = dup.brandid AND m.origin = dup.origin 
LEFT JOIN tags AS t ON t.productid = m.id 
LEFT JOIN groups AS g ON g.productid = m.id 
GROUP BY m.id 
ORDER BY `productName`,brandid,origin 

任何有关如何达到此目的的帮助和/或建议都非常有效。

+0

请参阅规范化。 – Strawberry

回答

1

我的猜测是你缺少对ID字段的子查询的聚合功能,也 - 你需要按产品名称,产地和品牌,而不是ID,以便试试这个:

SELECT m.*,dup.id AS dupid,GROUP_CONCAT(DISTINCT t.tagid ORDER BY t.tagid ASC) AS alltags,GROUP_CONCAT(DISTINCT g.groupid ORDER BY g.groupid ASC) AS groups 
FROM `products` m 
JOIN (SELECT min(id) as id,`productName`, brandid, origin, COUNT(*) AS c FROM products 
GROUP BY `productName`, brandid, origin HAVING c > 1) dup ON m.`productName` = dup.`productName` AND m.brandid = dup.brandid AND m.origin = dup.origin 
LEFT JOIN tags AS t ON t.productid = m.id 
LEFT JOIN groups AS g ON g.productid = m.id 
GROUP BY m.`productName`,m.brandid,m.origin 
ORDER BY m.`productName`,m.brandid,m.origin 

编辑 :您可以使用此查询:

SELECT tt.* 
FROM(
    SELECT m.*,GROUP_CONCAT(DISTINCT t.tagid ORDER BY t.tagid ASC) AS alltags,GROUP_CONCAT(DISTINCT g.groupid ORDER BY g.groupid ASC) AS groups 
    FROM `products` m 
    LEFT JOIN tags AS t ON t.productid = m.id 
    LEFT JOIN groups AS g ON g.productid = m.id 
    GROUP BY m.id) tt 
INNER JOIN 
    (SELECT productName,brandid,origin,alltags,groups 
    FROM 
     (SELECT m.*,GROUP_CONCAT(DISTINCT t.tagid ORDER BY t.tagid ASC) AS alltags,GROUP_CONCAT(DISTINCT g.groupid ORDER BY g.groupid ASC) AS groups 
     FROM `products` m 
     LEFT JOIN tags AS t ON t.productid = m.id 
     LEFT JOIN groups AS g ON g.productid = m.id 
     GROUP BY m.id) s 
    GROUP BY productName,brandid,origin,alltags,groups 
    HAVING COUNT(*) > 1) ss 
    ON(tt.productName = ss.productName and tt.brandid = ss.brandid and tt.origin = ss.origin 
    and tt.alltags = ss.alltags and tt.groups = ss.groups) 
+0

在SQLFiddle中尝试查询不会给出我期望的结果:(感谢您给它一个镜头,很多appriciated。 – entiendoNull

+0

它给你什么结果?也许它需要一点调整@entiendoNull – sagi

+0

我已经得到了结果可以在这里看到http://sqlfiddle.com/#!9/43f19/2在SQLFiddle中,我的目标是显示1,2,4,5的结果 – entiendoNull