在SQLite3中完全加入麻烦

时间:2016-05-08 07:23:05

标签: sql sqlite

我在SQLite 3中有一个如下所示的模式:

CREATE TABLE tags(id INTEGER PRIMARY KEY, tag TEXT NOT NULL, UNIQUE(tag));
CREATE TABLE files(id INTEGER PRIMARY KEY, name TEXT NOT NULL, UNIQUE(name));
CREATE TABLE filetags(file_id INT NOT NULL, tag_id INT NOT NULL, UNIQUE(file_id, tag_id), FOREIGN KEY(file_id) REFERENCES files(id), FOREIGN KEY(tag_id) REFERENCES tags(id));

我一直在尝试编写一个查询,对于给定的文件ID,它会显示每个标记以及是否为该ID设置了该标记。我能得到的最接近的是:

SELECT * FROM tags t 
LEFT OUTER JOIN filetags ft ON ft.tag_id=t.id 
LEFT OUTER JOIN files f ON f.id=ft.file_id WHERE f.id=@0 OR 
f.id IS NULL

这适用于具有1个或多个标记的文件,但对于没有标记的文件,它会排除所有至少包含一个文件的标记。我已经尝试了几种变体,但似乎受限于必须解决sqlite缺乏完整和正确的连接。

1 个答案:

答案 0 :(得分:1)

从概念开始:“我想要所有文件和所有标签”:

SELECT * FROM files f CROSS JOIN tags t

现在您需要附加“该文件是否确实设置了该标记”:

SELECT * FROM files f CROSS JOIN tags t
   LEFT JOIN filetags ft ON ft.file_id=f.id AND ft.tag_id=t.id

为了一点点的润色,它的化妆品别名:

SELECT f.*, t.*, (ft.file_id IS NOT NULL) AS file_has_tag
   FROM files f CROSS JOIN tags t
   LEFT JOIN filetags ft ON ft.file_id=f.id AND ft.tag_id=t.id