1

私はSQLでアイテムセットを表現しています(該当する場合はSQLite)。私のテーブルは次のようになります。

アイテムテーブル:

| 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には複数のItemが含まれている場合があり、この関係はItemset2Itemsテーブルで詳しく説明されています。

新しいアイテムセットがすでにテーブルにあるかどうかを確認し、ある場合はそのIDを見つけるにはどうすればよいですか?

たとえば、「高麗人参、にんにく、はちみつ」が既存のアイテムセットであるかどうかを確認したいと思います。これらの3つのIDを正確に含む単一のItemsetIdが存在するため、望ましい答えは「はい」になります。セットは順序付けられていないことに注意してください。「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指名手配リストのすべての が含まれています
  2. Item他のを含まない

この例では、そのようなアイテムセットが存在する場合、その ID を返します。

注:このソリューションは MySQL 用ですが@variable、バインド変数など、SQLite が理解できるものに s を変更すると、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 に答える