多对多SQL选择

时间:2011-09-14 09:20:52

标签: sql many-to-many

我目前正在编写标签云系统。

所以我编写了以下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”。

因此,我开发的下一步是选择链接到书签的所有标记,这些标记用选定标记列表标记。

例如,我传入参数“test”,它必须返回“braindead”和“example”,因为两者都标记有测试标记。

但是如果我传入参数“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

1 个答案:

答案 0 :(得分:0)

不确定这是否仍然存在问题,但查询应如下所示:

DECLARE @array TABLE(
    tag varchar(50)
)
INSERT INTO @array
VALUES('test')
INSERT INTO @array
VALUES('braindead')

select * from bookmark_model_bookmark
where id in(
    select bookmark_model_bookmark_id FROM bookmark_tag x INNER JOIN bookmark_model_tag t ON t.id = x.bookmark_model_tag_id
    where t.name in (select tag from @array)
    group by bookmark_model_bookmark_id
    having bookmark_model_bookmark_id >= (select count(0) from @array))

在上面的示例中,我使用了一个表,但是在逗号分隔的字符串输入上运行任何类型的拆分都会在类似的位置结束。让我知道这是你正在寻找的,或者如果我有错误的结束???谢谢,