我目前正在编写标签云系统。多对多SQL选择
所以我写了下面的SQL架构:
CREATE TABLE bookmark_model_bookmark (
id INTEGER NOT NULL,
link VARCHAR(255),
title VARCHAR(140),
description TEXT,
PRIMARY KEY (id)
);
CREATE TABLE bookmark_model_tag (
id INTEGER NOT NULL,
name VARCHAR(20),
PRIMARY KEY (id)
);
CREATE TABLE bookmark_tag (
bookmark_model_bookmark_id INTEGER NOT NULL,
bookmark_model_tag_id INTEGER NOT NULL,
PRIMARY KEY (bookmark_model_bookmark_id, bookmark_model_tag_id),
CONSTRAINT bookmark_model_bookmark_tags_fk FOREIGN KEY(bookmark_model_bookmark_id) REFERENCES bookmark_model_bookmark (id),
CONSTRAINT bookmark_model_tag_bookmarks_fk FOREIGN KEY(bookmark_model_tag_id) REFERENCES bookmark_model_tag (id)
);
而且随着数据量小的填充:
SELECT * FROM bookmark_model_bookmark;
1|http://braindead.fr|braindead|
2|http://example.fr|example|example text
SELECT * FROM bookmark_model_tag;
1|test
2|braindead
3|example
SELECT * FROM bookmark_tag;
1|1
1|2
2|1
2|3
在更具可读性方面:
- 书签#1名为braindead参考http://braindead.fr/并有两个标签:“test”和“braindead”。
- 书签#2命名示例参考http://example.fr/并且必须标记“test”和“example”。
因此,我开发的下一步是选择链接到书签的所有标签,这些书签用选定标签列表标记。
例如,我传入参数“测试”它必须返回“braindead”和“示例”,因为两者都标有测试标签。
但是,如果我传入参数“test”和“braindead”,则只有“braindead”必须由查询返回,因为它是唯一标记了“test”和“braindead”的书签。
SELECT *
FROM bookmark_model_tag AS tag
INNER JOIN bookmark_tag ON (bookmark_tag.bookmark_model_tag_id = tag.id)
WHERE bookmark_tag.bookmark_model_bookmark_id IN (/* Here my subquery */);
但我无法设法找出子查询。我有这样的开始:
SELECT bookmark.id
FROM bookmark_model_bookmark AS bookmark
INNER JOIN bookmark_tag ON (bookmark.id = bookmark_tag.bookmark_model_bookmark_id)
WHERE /* what to write here ? */
只是要准确,我的查询的输入参数是标签ID的数组。
所以在这里我卡住了。
编辑
我使用的ORM(SQLAlchemy的),用于建立自己的查询,这是建立查询,看起来像这样:
SELECT tag.id AS tag_id, tag.name AS tag_name, count(tag.id) AS count_1
FROM tag, bookmark_tag, (
SELECT bookmark.id AS id
FROM bookmark, bookmark_tag
WHERE bookmark.id = bookmark_tag.bookmark_id
AND bookmark_tag.tag_id IN (1, 2)
GROUP BY bookmark.id
HAVING count(bookmark.id) = 2) AS anon_1
WHERE tag.id = bookmark_tag.tag_id
AND bookmark_tag.bookmark_id = anon_1.id
AND tag.id NOT IN (1, 2)
GROUP BY tag.id
这是[Relational Division](http://www.simple-talk.com/sql/t-sql-programming/divided-we-stand-the-sql-of-relational-division/)。最常用的方法似乎是'GROUP BY'和'COUNT' –
我的Where子句现在是“WHERE bookmark_tag.bookmark_model_tag_id IN($ TAG_LIST_ID)GROUP BY bookmark.id HAVING count(*)== $ TAG_LIST_SIZE”。这是你所期望的吗? –
是的。假设'bookmark_tag'有一个唯一的约束,所以你不能有相同组合的重复。 –