Как мне создать таблицу перекрестных ссылок / запрос для моих данных?

StackOverflow https://stackoverflow.com/questions/321127

Вопрос

У меня есть две простые таблицы в моей базе данных.Таблица "card", содержащая идентификатор, название и текст карточки, и таблица "rulings", содержащая идентификатор карточки и текст с подробным описанием правил для карточки.

Достаточно часто в тексте постановления содержится ссылка на другую карточку в базе данных.Найти это в тексте достаточно легко, потому что каждая карточка заключена в тексте в кавычки.Нередко в тексте постановления упоминается несколько карточек.

Что я хотел бы сделать, так это иметь возможность создать таблицу перекрестных ссылок (или процедуру, если она достаточно эффективна), чтобы при отправке запроса на карточку я мог найти все записи правил, которые напрямую ссылаются на карточку через идентификатор, и получить все записи правил, где в тексте упоминается название карточки.

Как бы лучше всего подойти к этому?Моей средой является SQL 2005, но здесь широко принимаются любые решения, не зависящие от базы данных.

Это было полезно?

Решение

Это похоже на довольно простую и распространенную проблему отношений, которая решается с помощью таблицы перекрестных ссылок. Например:

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

Все это было у меня в голове и не проверялось, поэтому могут быть синтаксические ошибки и т. д.

Ваш интерфейс будет отвечать за ведение ссылок. Это, вероятно, желательно, так как позволяет избежать проблемы, когда кто-то забывает ставить кавычки вокруг имени карты в тексте и т. Д.

Другие советы

Я бы рекомендовал вам создать еще одну таблицу, в которой хранятся ваши ссылки.Затем создайте триггер вставки и обновления, который поддерживает эту таблицу.Таким образом, у вас будет более быстрый запрос для возврата данных, которые вы ищете.

Я понимаю, что первоначальное заполнение этой таблицы может быть немного затруднено, именно поэтому я показываю ниже некоторые примеры данных (и запросов), которые вы можете использовать для начала работы.

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) + '"%'

Редактировать:

Причина, по которой я предложил другую таблицу, заключается в том, что вы, скорее всего, будете разочарованы производительностью этого запроса, особенно для больших таблиц.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top