如何查找是否存在无序项集

时间:2012-07-29 11:54:23

标签: sql sqlite

我在SQL中表示项目集(SQLite,如果相关)。我的表看起来像这样:

ITEMS表:

| ItemId | Name    |
| 1      | Ginseng |
| 2      | Honey   |
| 3      | Garlic  |

项集:

| ItemSetId | Name                |
| ...       | ...                 |
| 7         | GinsengHoney        |
| 8         | HoneyGarlicGinseng  |
| 9         | Garlic              |

ITEMSETS2ITEMS

| ItemsetId | ItemId |
| ...       | ....   |
| 7         | 1      |
| 7         | 2      |
| 8         | 2      |
| 8         | 1      |
| 8         | 3      |

如您所见,Itemset可能包含多个Items,这种关系在Itemset2Items表中有详细说明。

如何检查表中是否已有新项目集,如果是,请查找其ID?

例如,我想检查“人参,大蒜,蜂蜜”是否为现有项目集。所需答案为“是”,因为存在单个ItemsetId,其中包含完全这三个ID。请注意,该集合是无序的:对“蜂蜜,大蒜,人参”的查询应该表现相同。

我该怎么做?

2 个答案:

答案 0 :(得分:1)

我建议您首先将要检查的项目集放入表格中,每个项目一行。

现在的问题是这个“提议的”项目集与其他项目集的重叠。以下查询提供了答案:

select itemsetid,
from (select coalesce(ps.itemid, is2i.itemid) as itemid, is2i.itemsetid,
             max(case when ps.itemid is not null then 1 else 0 end) as inProposed,
             max(case when is2i.itemid is not null then 1 else 0 end) as inItemset
      from ProposedSet ps full outer join
           ItemSets2items is2i
           on ps.itemid = is2i.itemid
      group by coalesce(ps.itemid, is2i.itemid), is2i.itemsetid
     ) t
group by itemsetid
having min(inProposed) = 1 and min(inItemSet) = 1

这将所有项目集加入所有项目集。然后,它按每个项目集中的项目进行分组,并给出关于项目是否在集合中的标记。最后,它检查项目集中的所有项目是否都在。

答案 1 :(得分:0)

听起来你需要找到一个ItemSet

  1. 包含所需列表中的所有Item
  2. 不包含任何其他Item s
  3. 此示例将返回此类项集的ID(如果存在)。

    注意:此解决方案适用于MySQL,但是一旦您将@variable更改为SQLite理解的内容,它就可以在SQLite中运行,例如:绑定变量。

    
    -- these are the IDs of the items in the new itemset
    -- if you add/remove some, make sure to change the IN clauses below
    set @id1 = 1;
    set @id2 = 2;
    
    -- this is the count of items listed above
    set @cnt = 2;
    
    SELECT S.ItemSetId FROM ItemSets S
    
    INNER JOIN
    (SELECT ItemsetId, COUNT(*) as C FROM ItemSets2Items 
    WHERE ItemId IN (@id1, @id2)
    GROUP BY ItemsetId
     HAVING COUNT(*) = @cnt
    ) I -- included ingredients
    ON I.ItemsetId = S.ItemSetId
    
    LEFT JOIN
    (SELECT ItemsetId, COUNT(*) as C FROM ItemSets2Items 
    WHERE ItemId NOT IN (@id1, @id2)
    GROUP BY ItemsetId
    ) A -- additional ingredients
    ON A.ItemsetId = S.ItemSetId
    
    WHERE A.C IS NULL
    

    请参阅fiddle for MySQL