1

我代表 SQL 中的项集(SQLite,如果相关)。我的表如下所示:

项目表:

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

项目组:

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

项目集2项目

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

如您所见,一个 Itemset 可能包含多个 Item,并且这种关系在 Itemset2Items 表中进行了详细说明。

如何检查表中是否已经有新的项集,如果是,找到它的 ID?

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

我怎样才能做到这一点?

4

2 回答 2

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

这将所有建议的项目与所有项目集连接起来。然后它按每个项目集中的项目分组,给出一个关于项目是否在集合中的标志。最后,它检查项目集中的所有项目是否都在两者中。

于 2012-07-29T13:33:35.960 回答
0

听起来你需要找到一个ItemSet

  1. 包含Item您想要的列表中的所有 s
  2. 不包含任何其他Items

此示例将返回此类项目集的 ID(如果存在)。

注意:此解决方案适用于 MySQL,但一旦您将@variables 更改为 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

参见MySQL 的小提琴

于 2012-07-29T12:50:10.513 回答