How do I create a cross reference table/query for my data?

后端 未结 2 1320
清歌不尽
清歌不尽 2020-12-04 00:50

I have two simple tables in my database. A \"card\" table that contains Id, Name, and text of a card, and a \"rulings\" table which contains the Id of the card, and text det

相关标签:
2条回答
  • 2020-12-04 01:11

    I would recommend that you create another table that stores your references. Then, create an insert and update trigger that maintains this table. This way, you would have a faster query to return the data you are looking for.

    I recognize that initially populating this table might be a little difficult, which is why I am showing some sample data (and query) below, that you can use to get you started.

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

    EDIT:

    The reason I suggested another table is because you will likely be disappointed with the performance of this query, especially for large tables.

    0 讨论(0)
  • This seems like a fairly simple and common relational problem that is solved by a cross-reference table. For example:

    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
    

    To get all card rulings for a card:

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

    To get all cards referenced in a ruling by a given card:

    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
    

    This was all off the top of my head and is not tested, so there might be syntactic errors, etc.

    Your front end would be responsible for maintaining the references. This is probably desirable since it avoids the issue of someone forgetting to put quotes around a card name in a ruling text, etc.

    0 讨论(0)
提交回复
热议问题