2

データベースに 2 つの単純なテーブルがあります。カードの ID、名前、テキストを含む「カード」テーブルと、カードの ID とカードの裁定を詳述するテキストを含む「裁定」テーブル。

多くの場合、裁定テキストには、データベース内の別のカードへの参照があります。テキスト内の各カードは引用符で囲まれているため、テキスト内でこれを見つけるのは簡単です。裁定のテキスト内で複数のカードが参照されることは珍しくありません。

私がやりたいことは、カードのクエリを送信するときに、カードを直接参照するすべての裁定レコードをカード名がテキストで参照されているすべての裁定レコードを Id して取得します。

これにアプローチする最良の方法は何ですか?私の環境は SQL 2005 ですが、ここではあらゆる種類の「DB にとらわれない」ソリューションが大いに受け入れられます。

4

2 に答える 2

4

これは、相互参照テーブルによって解決される、かなり単純で一般的なリレーショナル問題のように思えます。例えば:

CREATE TABLE dbo.Cards (
    id        INT            NOT NULL,
    name      VARCHAR(50)    NOT NULL,
    card_text VARCHAR(4000)  NOT NULL,
    CONSTRAINT PK_Cards PRIMARY KEY CLUSTERED (id)
)
GO
CREATE TABLE dbo.Card_Rulings (
    card_id        INT            NOT NULL,
    ruling_number  INT            NOT NULL,
    ruling_text    VARCHAR(4000)  NOT NULL,
    CONSTRAINT PK_Card_Rulings PRIMARY KEY CLUSTERED (card_id, ruling_number)
)
GO
CREATE TABLE dbo.Card_Ruling_Referenced_Cards (
    parent_card_id    INT    NOT NULL,
    ruling_number     INT    NOT NULL,
    child_card_id     INT    NOT NULL,
    CONSTRAINT PK_Card_Ruling_Referenced_Cards PRIMARY KEY CLUSTERED (parent_card_id, ruling_number, child_card_id)
)
GO
ALTER TABLE dbo.Card_Rulings
ADD CONSTRAINT FK_CardRulings_Cards FOREIGN KEY (card_id) REFERENCES dbo.Cards(id)
GO
ALTER TABLE dbo.Card_Ruling_Referenced_Cards
ADD CONSTRAINT FK_CardRulingReferencedCards_CardRulings FOREIGN KEY (parent_card_id, ruling_number) REFERENCES dbo.Card_Rulings (card_id, ruling_number)
GO
ALTER TABLE dbo.Card_Ruling_Referenced_Cards
ADD CONSTRAINT FK_CardRulingReferencedCards_Cards FOREIGN KEY (child_card_id) REFERENCES dbo.Cards(id)
GO

カードのすべてのカード ルーリングを取得するには:

SELECT *
FROM dbo.Cards C
INNER JOIN dbo.Card_Rulings CR ON CR.card_id = C.id
WHERE C.id = @card_id

特定のカードによる裁定で参照されているすべてのカードを取得するには:

SELECT C.*
FROM dbo.Card_Rulings CR
INNER JOIN dbo.Card_Ruling_Referenced_Cards CRRC ON CRRC.parent_card_id = CR.card_id
INNER JOIN dbo.Cards C ON C.id = CRRC.child_card_id
WHERE CR.card_id = @card_id

これはすべて私の頭の上にあり、テストされていないため、構文エラーなどがある可能性があります.

フロントエンドは、参照を維持する責任があります。これは、誰かが裁定テキストなどでカード名を引用符で囲むのを忘れるという問題を回避するため、おそらく望ましいものです。

于 2008-11-26T15:57:59.073 に答える
1

参照を格納する別のテーブルを作成することをお勧めします。次に、このテーブルを維持する挿入および更新トリガーを作成します。このようにして、探しているデータを返すためのより高速なクエリが得られます。

最初にこのテーブルにデータを入力するのは少し難しいかもしれません。そのため、以下にいくつかのサンプル データ (およびクエリ) を示しています。これを使用して作業を開始できます。

Declare @Card Table(Id Int, Name VarChar(20), CardText VarChar(8000))

Declare @Ruling Table(CardId Int, CardRuling VarChar(8000))

Insert Into @Card Values(1, 'Card 1', 'This is the card ID = 1')
Insert Into @Card Values(2, 'Card 2', 'This is the card id = 2.')
Insert Into @Card Values(3, 'Card 3', 'This is the card id = 3.')

Insert Into @Ruling Values(1, 'This is the ruling for 1 which references "2"')
Insert Into @Ruling Values(2, 'This is the ruling for 2 which references nothing')
Insert Into @Ruling Values(3, 'This is the ruling for 3 which references "1" and "2"')

Declare @CardId Int
Set @CardId = 1

Select  * 
From    @Card As Card
        Inner Join @Ruling As Ruling
            On Card.Id = Ruling.CardId
        Left Join @Card As CardReferences
            On Ruling.CardRuling Like '%"' + Convert(VarChar(10), CardReferences.Id) + '"%'

編集:

別のテーブルを提案した理由は、特に大きなテーブルの場合、このクエリのパフォーマンスに失望する可能性が高いためです。

于 2008-11-26T15:55:57.407 に答える