我目前正在編寫標籤雲系統。多對多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'有一個唯一的約束,所以你不能有相同組合的重複。 –