4

レコードが特定のオブジェクトを表すテーブルがあります。簡単にするために、テーブルには1つの列しかなく、それが一意であると想定しますObjectId。次に、そのテーブルのオブジェクトの組み合わせを保存する方法が必要です。組み合わせは一意である必要がありますが、任意の長さにすることができます。たとえば、私ObjectId

1,2,3,4

次の組み合わせを保存したい:

{1,2}, {1,3,4}, {2,4}, {1,2,3,4}

注文は必要ありません。私の現在の実装は、 sをsにCombinationsマップするテーブルを持つことです。したがって、すべての組み合わせは一意のIDを受け取ります。ObjectIdCombinationId

ObjectId | CombinationId
------------------------
1        | 1
2        | 1
1        | 2
3        | 2
4        | 2

これは、上記の例の最初の2つの組み合わせのマッピングです。問題は、特定の組み合わせを見つけるためのクエリCombinationIdが非常に複雑に見えることです。このテーブルの2つの主な使用シナリオは、すべての組み合わせを反復処理し、特定の組み合わせを取得することです。テーブルは一度作成され、更新されることはありません。JDBCを介してSQLiteを使用しています。このようなマッピングを実装するためのより簡単な方法またはベストプラクティスはありますか?

4

3 に答える 3

2

問題は、特定の組み合わせのCombinationIdを見つけるためのクエリが非常に複雑に見えることです。

悪くないはずです。選択したアイテムを含むすべての組み合わせ(追加のアイテムを許可)が必要な場合は、次のようになります。

SELECT combinationID
FROM Combination
WHERE objectId IN (1, 3, 4)
GROUP BY combinationID
HAVING COUNT(*) = 3 -- The number of items in the combination

特定の組み合わせのみが必要な場合(追加のアイテムは許可されません)、次のようになります。

SELECT combinationID FROM (
   -- ... query from above goes here, this gives us all with those 3
) AS candidates

-- This bit gives us a row for each item in the candidates, including 
-- the items we know about but also any 'extras'
INNER JOIN combination ON (candidates.combinationID = combination.combinationID)

GROUP BY candidates.combinationID
HAVING COUNT(*) = 3 -- Because we joined back on ALL, ones with extras will have > 3

ここ(または元のクエリ)でNOT EXISTSを使用することもできますが、これは説明が簡単なようです。

最後に、あなたは空想的で、単一の単純なクエリを持つこともできます

SELECT combinationID
FROM Combination AS candidates
INNER JOIN Combination AS allItems ON 
  (candidates.combinationID = allItems.combinationID)
WHERE candidates.objectId IN (1, 3, 4)
GROUP BY combinationID
HAVING COUNT(*) = 9 -- The number of items in the combination, squared

つまり、{1、2}を探していて、{1、2、3}との組み合わせがある場合、{candidates、allItems}JOINの結果は次のようになります。

{1, 1}, {1, 2}, {1, 3}, {2, 1}, {2, 2}, {2, 3}

余分な3は、4ではなくCOUNT(*)6行になりGROUPます。したがって、これは、私たちが求めている組み合わせではないことがわかります。

于 2010-05-19T12:56:51.877 に答える
1

これは異端かもしれませんが、使用シナリオでは、組み合わせ自体をある種の複合(テキスト)値として格納する非正規化構造を使用する方が適切な場合があります。

CombinationId | Combination
---------------------------
1             | |1|2|
2             | |1|3|4|

複合値を生成するときに常にObjectIdをソートするというルールを作成すると、特定のオブジェクトのセットの組み合わせを簡単に取得できます。

于 2010-05-19T11:48:05.047 に答える
0

もう1つのオプションは、関係値属性を使用することです。これは、SQLDBMSではマルチセットまたはネストされたテーブルと呼ばれます。

セット自体以外のオブジェクトのセットの識別子がない場合、関係値属性は意味をなす場合があります。ただし、SQL DBMSでは、そのタイプの列でキーを宣言することはできないと思います。そのため、使用できる代替キーがない場合は問題になる可能性があります。

http://download.oracle.com/docs/cd/B10500_01/appdev.920/a96594/adobjbas.htm#458790

于 2010-05-19T12:16:06.540 に答える