Выбор SQL «многие ко многим» - PullRequest
0 голосов
/ 14 сентября 2011

Я сейчас пишу облачную систему тегов.

Итак, я написал следующую схему 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 ? */

Если быть точным, входным параметром моего запроса является массив идентификаторов тегов.

Итак, я застрял.

EDIT

Я использую 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 голосов
/ 17 января 2012

Не уверен, что это все еще проблема, но запрос должен выглядеть примерно так:

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))

В приведенном выше примере я использовал таблицу, но вы выполняете любое разделение на вводе строки, разделенном запятыми, в конечном итоге в аналогичной позиции. Дайте мне знать, если это было то, что вы искали или у меня неправильный конец палки ??? Спасибо,

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...