1

この問題にどのデータ構造/ストレージ戦略を使用すべきか知りたいのですが。

データベース内の各データエントリは、ABCDなどの複数の順序付けされたアイテムのリストで構成されます。A、B、C、Dは異なるアイテムです。

データベースに3つのエントリがあるとします。

あいうえお

EFG

GHBA

ユーザーが順序付けされていないアイテムを入力すると、データベースから一致する順序付けされたエントリを見つける必要があります。たとえば、ユーザーがA、B、G、Hと入力した場合、データベースからユーザーにGHBAを返したいと思います。

私のデータストレージ戦略はどうあるべきですか?

4

2 に答える 2

1

リストを個々のアイテムに分割し、そのレベルで作業します。

いくつかのテーブル:

リスト

  • ID(PK)
  • シーケンス(上記の「ABCD」エントリ)
  • [ことなど]

アイテム

  • ID(PK)
  • 名前(値、単語、意味のあるものは何でも)
  • [ことなど]

list_items

  • list_ID
  • item_ID
  • [「GHBA」と「ABGH」が異なるシーケンスと見なされる場合の序数int]

(その1つにPK list_ID、item_ID [、序数]を合成し、基本的に多く:多くの関係)

一部のデータなので、表が何を表しているかがより明確になります。

INSERT INTO items (ID, name) VALUES (1, 'A'), (2, 'B'), (3, 'G'), (4, 'H');
INSERT INTO lists (ID, sequence) VALUES (1, 'A-B-G-H');
INSERT INTO list_items (list_ID, item_ID) VALUES (1, 1), (1, 2), (1, 3), (1, 4);
INSERT INTO lists (ID, sequence) VALUES (2, 'B-A-G');
INSERT INTO list_items (list_ID, item_ID) VALUES (2, 2), (2, 1), (2, 3);

そして最後に、すべてのアイテム(A、B、G、H)を含むリストを見つけるには:

SELECT lists.sequence FROM lists
JOIN list_items ON lists.ID = list_items.list_ID
JOIN items AS i1 ON list_items.item_ID = i1.ID HAVING i1.name = 'A'
JOIN items AS i2 ON list_items.item_ID = i2.ID HAVING i2.name = 'B'
JOIN items AS i3 ON list_items.item_ID = i3.ID HAVING i3.name = 'G'
JOIN items AS i4 ON list_items.item_ID = i4.ID HAVING i4.name = 'H'

これにより、「ABGH」、「GHAB」、「HATBAG」などのリストが返されますが、「BUGHUT」(Aなし)または「BATH」(Gなし)は返されません。すべての条件が満たされている必要があります。「任意の」検索を実行することは、もう少し複雑になる可能性があります(昼食時に頭の中でこれを書くと、RIGHT JOINおそらくすべての種類の重複と速度低下が発生します)。

ゲノムをマッピングしたり、人間の言語を再定義したりすることはありませんが、適切なサイズのデータ​​セットでは問題ないはずです。WHERE sequence LIKE '%A%' AND sequence LIKE '%B%'いずれにせよ、新しいデータを追加するための余分な作業を絶対に処理できない場合を除いて、各リストをvarcharとして保存したり「」を実行したりすることは避けたいと思います。

于 2010-02-09T20:51:36.860 に答える
1

順序付けされた要素と順序付けされていない要素を別々に保存することをお勧めします。そうしないと、順序付けられた要素のすべての順列を検索する必要があり、時間がかかります。

これを試して:

/* Create a table to track your items (A, B, C, etc.). It contains all possible elements */
CREATE TABLE [Items](
    [Value] [char](1) NOT NULL,
 CONSTRAINT [PK_Items] PRIMARY KEY CLUSTERED ([Value]))

/* Create a table to track their grouping and stated ordering */
CREATE TABLE [Groups](
    [ID] [int] NOT NULL,
    [Order] [text] NOT NULL,
 CONSTRAINT [PK_Groups] PRIMARY KEY CLUSTERED ([ID]))

/* Create a mapping table to associate them */
CREATE TABLE [ItemsToGroups](
    [Item] [char](1) NOT NULL,
    [Group] [int] NOT NULL
)

ALTER TABLE [ItemsToGroups]  WITH CHECK ADD CONSTRAINT [FK_ItemsToGroups_Groups] FOREIGN KEY([Group])
REFERENCES [Groups] ([ID])

ALTER TABLE [ItemsToGroups] CHECK CONSTRAINT [FK_ItemsToGroups_Groups]

ALTER TABLE [ItemsToGroups]  WITH CHECK ADD CONSTRAINT [FK_ItemsToGroups_Items] FOREIGN KEY([Item])
REFERENCES [Items] ([Value])

ALTER TABLE [ItemsToGroups] CHECK CONSTRAINT [FK_ItemsToGroups_Items]

/* Populate your tables. 
   Items should have eight rows: A, B, C,...H
   Groups should have three rows: 1:ABCD, 2:EFG, 3:GHBA
   Items to groups should have eleven rows: A:1, B:1,...A:3 */

/* You will want to pass in a table of values, so set up a table-valued parameter
   First, create a type to support your input list */
CREATE TYPE ItemList AS TABLE (e char(1) NOT NULL PRIMARY KEY)
DECLARE @Input ItemList
GO

/* Create a stored procedure for your query */
CREATE PROCEDURE SelectOrderedGroup @Input ItemList READONLY AS
    SELECT *
    FROM Groups
    WHERE Groups.ID NOT IN (
        SELECT [Group]
        FROM ItemsToGroups
        WHERE Item NOT IN (SELECT e FROM @Input)
    )
GO

/* Now when you want to query them: */
DECLARE @MyList ItemList
INSERT @MyList(e) VALUES('G'),('H'),('B'),('A')
EXEC SelectOrderedGroup @MyList

上記はあなたが望むように3:GHBAを返します。DCBAを渡すと、探しているように1:ABCDが返されます。Cだけで構成されるグループはないため、Cを渡すと、何も返されません。

上記のように、入力にテーブル値パラメーターを使用することをお勧めしますが、最終的なSELECTを単純なリストに変換して、ItemListタイプを削除することもできます。

于 2010-02-09T23:18:43.750 に答える