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

Vas*_*ily 1 sql sqlite many-to-many group-concat

我在使用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);
Run Code Online (Sandbox Code Playgroud)

这是标签的表格:

CREATE TABLE Tags (TagId INTEGER PRIMARY KEY AUTOINCREMENT,
                   Name TEXT UNIQUE NOT NULL);
Run Code Online (Sandbox Code Playgroud)

这是交叉引用表:

CREATE TABLE CardsRelatedToTags (CardId INTEGER,
                                 TagId INTEGER,
                                 PRIMARY KEY (CardId, TagId));
Run Code Online (Sandbox Code Playgroud)

我需要在一个用逗号分隔的列中获取一张带有相关标签的卡片表.我已经可以通过以下查询获知我需要知道其Id的单行所需的内容:

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
Run Code Online (Sandbox Code Playgroud)

这将导致类似这样的事情:

CardId | Text                          | TagsList
1      | Some specially formatted text | Tag1, Tag2, TagN...
Run Code Online (Sandbox Code Playgroud)

如何使用SQL查询为卡中的每一行获取此类结果(来自group_concat的TagsList)从性能的角度来看,建议这样做吗?或者我需要使用更简单的DB请求在应用程序代码中进行这种"演示"工作?

Kam*_*ski 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
Run Code Online (Sandbox Code Playgroud)

现在,关于表现的问题.数据库是一个功能强大的工具,不会以简单的SELECT语句结束.你绝对可以在DB(甚至是SQLite)中做你需要的.将SELECT语句用作另一个SELECT中的一个列的提要是一种不好的做法.它需要扫描一个表来获取输入中每一行的结果.