2015-04-14 60 views
1

我有一個使用SQLite構建的應用程序的小型flashcard中的多對多關係的經典安排。每張卡可以有多個標籤,每個標籤可以有多張卡。這兩個實體每個表都有一個第三個表來鏈接記錄。SQLite,多對多關係,如何聚合?

這是卡表:

CREATE TABLE Cards (CardId INTEGER PRIMARY KEY AUTOINCREMENT, 
        Text TEXT NOT NULL, 
        Answer INTEGER NOT NULL, 
        Success INTEGER NOT NULL, 
        Fail INTEGER NOT NULL); 

這是標籤表:

CREATE TABLE Tags (TagId INTEGER PRIMARY KEY AUTOINCREMENT, 
        Name TEXT UNIQUE NOT NULL); 

這是交叉引用表:

CREATE TABLE CardsRelatedToTags (CardId INTEGER, 
           TagId INTEGER, 
           PRIMARY KEY (CardId, TagId)); 

我需要得到用逗號分隔的一列卡片及其相關標籤。 我已經得到了我需要一個單行知道其編號與下面的查詢:

SELECT Cards.CardId, Cards.Text, 
     (SELECT group_concat(Tags.Name, ', ') FROM Tags 
      JOIN CardsRelatedToTags ON CardsRelatedToTags.TagId = Tags.TagId 
      WHERE CardsRelatedToTags.CardId = 1) AS TagsList 
      FROM Cards 
      WHERE Cards.CardId = 1 

這將導致這樣的事情:

CardId | Text       | TagsList 
1  | Some specially formatted text | Tag1, Tag2, TagN... 

如何獲得這種類型的結果(來自group_concat的TagsList)卡片中的每一行使用SQL查詢?從性能的角度來看,這是明智的做法嗎?或者我需要在應用程序代碼中使用對數據庫更簡單的請求來完成這種「演示」工作?

回答

5

回答您的代碼的問題:

SELECT 
    c.CardId, 
    c.Text, 
    GROUP_CONCAT(t.Name,', ') AS TagsList 
FROM 
    Cards c 
    JOIN CardsRelatedToTags crt ON 
     c.CardId = crt.CardId 
    JOIN Tags t ON 
     crt.TagId = t.TagId 
WHERE 
    c.CardId = 1 
GROUP BY c.CardId, c.Text 

現在,業績的問題。數據庫是一個強大的工具,不會以簡單的SELECT語句結束。你一定可以在數據庫中做你需要的東西(甚至是SQLite)。將SELECT語句用作另一個SELECT中的一列的提要是一種不好的做法。這將需要掃描一個表格以獲取輸入中每行的結果。

+0

將'WHERE c.CardId = 1'修改爲'WHERE c.Card> 0'或通過刪除它來獲得我所需要的,完美的。非常感謝。 – Vasily

+0

很高興我可以幫助:) –