我在使用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);
这是Tags:
的表格CREATE TABLE Tags (TagId INTEGER PRIMARY KEY AUTOINCREMENT,
Name TEXT UNIQUE NOT NULL);
这是交叉引用表:
CREATE TABLE CardsRelatedToTags (CardId INTEGER,
TagId INTEGER,
PRIMARY KEY (CardId, TagId));
我需要在一个用逗号分隔的列中获取一张带有相关标签的卡片表。 我已经可以通过以下查询得到我需要的单行知道其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
这将导致类似这样的事情:
CardId | Text | TagsList
1 | Some specially formatted text | Tag1, Tag2, TagN...
如何使用SQL查询为卡中的每一行获取此类结果(来自group_concat的TagsList)?建议从性能点开始视图?或者我需要做这种"演示"使用更简单的DB请求在应用程序代码中工作?
答案 0 :(得分: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语句结束。你绝对可以在DB(甚至是SQLite)中做你需要的。将SELECT语句用作另一个SELECT中的一个列的提要是一种不好的做法。它需要扫描一个表来获得输入中每一行的结果。