SQLite,多对多关系,如何聚合?

SQLite, Many to many relations, How to aggregate?

我在使用 SQLite 构建的类似应用程序的小型闪存卡中对多对多关系进行了经典安排。每张卡片可以有多个标签,每个标签可以有多个卡片。这两个实体各有一个 table 和第三个 table 到 link 条记录。

这是卡片的table:

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

这是 table 标签:

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

这是交叉引用table:

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

我需要在用逗号分隔的列中获取 table 卡片及其相关标签。 我已经可以通过以下查询获得单行所需的信息:

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...

如何使用 SQL 查询获取卡片中每一行的此类结果(来自 group_concat 的 TagsList) 从性能的角度来看,这样做是否明智?或者我需要使用对数据库的更简单请求在应用程序代码中完成这种 "presentation" 工作?

正在回答您的代码问题:

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 中的一列的提要是一种不好的做法。它需要扫描 table 以获得输入中每一行的结果。