跨多个表进行选择

问题描述 投票:0回答:1

我有三个 SQLite 表,使用以下脚本创建

PRAGMA foreign_keys = ON;

CREATE TABLE IF NOT EXISTS entries(
    timestamp TEXT,
    title TEXT,
    body TEXT
);

CREATE TABLE IF NOT EXISTS tags(
    tag TEXT
);

CREATE TABLE IF NOT EXISTS entry_tags(
    entry_id INTEGER;
    tag_id INTEGER,
    FOREIGN KEY (entry_id) REFERENCES entries(rowid),
    FOREIGN KEY (tag_id) REFERENCES tags(rowid)
);

我的问题很简单,但我不知道如何回答。如何使用 SQL 获取条目的时间戳、标题、正文和所有关联标签?我假设它涉及到过程中某个地方的 JOIN,但尽管进行了搜索,我找不到我能理解的答案。

sql sqlite
1个回答
0
投票

是的,您想使用您的

entry_tags
连接表进行 JOIN。像这样的东西(注意我只是使用 Sqlite 命令行工具,而不是 Python 模块,但 SQL 命令是相同的):

sqlite> select e.timestamp, e.title, e.body, t.tag 
   ...> from entries as e 
   ...>      join entry_tags et on e.rowid = et.entry_id
   ...>      join tags as t on et.tag_id = t.rowid;
┌────────────┬───────────┬────────────────┬───────┐
│ timestamp  │   title   │      body      │  tag  │
├────────────┼───────────┼────────────────┼───────┤
│ 2024-11-01 │ Article A │ blah blah blah │ alpha │
│ 2024-11-01 │ Article A │ blah blah blah │ beta  │
└────────────┴───────────┴────────────────┴───────┘

但是,请注意,如果一篇文章上有多个标签,您将获得重复的行。在这种情况下,您可以使用

group_concat
函数(参见sqlite中的字符串聚合)来聚合标签(默认以逗号分隔):

sqlite> select e.timestamp, e.title, e.body, group_concat(t.tag) as tags 
   ...> from entries as e 
   ...>      join entry_tags et on e.rowid = et.entry_id
   ...>      join tags as t on et.tag_id = t.rowid;
┌────────────┬───────────┬────────────────┬────────────┐
│ timestamp  │   title   │      body      │    tags    │
├────────────┼───────────┼────────────────┼────────────┤
│ 2024-11-01 │ Article A │ blah blah blah │ alpha,beta │
└────────────┴───────────┴────────────────┴────────────┘

顺便说一句,请注意,Sqlite 通常不会让您使用隐式

rowid
列作为主键并引用作为外键,除非您显式地将其放入表架构中(请参阅 https://www.sqlite .org/rowidtable.html)。例如,您应该如下定义
entries
tags

CREATE TABLE entries(
    rowid INTEGER PRIMARY KEY,
    timestamp TEXT,
    title TEXT,
    body TEXT
);
CREATE TABLE tags(
    rowid INTEGER PRIMARY KEY,
    tag TEXT
);
© www.soinside.com 2019 - 2024. All rights reserved.