【问题标题】:How to create an sql query for a tag system with multiple tags?如何为具有多个标签的标签系统创建 sql 查询?
【发布时间】:2020-07-23 13:34:35
【问题描述】:

我有 3 个表,但不知道如何创建一系列 sql 查询(或者如果可能,只创建一个复杂查询)。这些表格是:

CREATE TABLE IF NOT EXISTS excerpt(
  excerptID INT UNSIGNED NOT NULL AUTO_INCREMENT, 
  author VARCHAR(45) NOT NULL, 
  title VARCHAR(255) NOT NULL, 
  text VARCHAR(1000) NOT NULL,
  comments VARCHAR(1000) NOT NULL,
  PRIMARY KEY (excerptID)
) ENGINE=INNODB CHARACTER SET utf8mb4;

CREATE TABLE IF NOT EXISTS tag(
  tagID INT UNSIGNED NOT NULL AUTO_INCREMENT,
  description VARCHAR(45) NOT NULL , 
  PRIMARY KEY (tagID)
) ENGINE=INNODB CHARACTER SET utf8mb4;

CREATE TABLE IF NOT EXISTS tagmap (
  excerptID INT UNSIGNED NOT NULL, 
  tagID INT UNSIGNED NOT NULL, 
  PRIMARY KEY (excerptID, tagID),
    CONSTRAINT excerptFK FOREIGN KEY (excerptID) REFERENCES excerpt (excerptID)
    ON DELETE CASCADE 
    ON UPDATE CASCADE,
    CONSTRAINT tagFK FOREIGN KEY (tagID) REFERENCES tag (tagID)
    ON DELETE CASCADE 
    ON UPDATE CASCADE
) ENGINE=INNODB;

基于 description 参数,我需要返回与绑定到该描述的所有摘录相关的所有标签描述。例如,如果我有四个摘录

Excerpt(1, aaaa , aaaa, aaaa, aaaa) bound via tagmap to tags (A, B, C)
Excerpt(2, bbbb, bbbb, bbbb, bbbb) bound via tagmap tags (A, D)
Excerpt(3, cccc, cccc, cccc, cccc) bound via tagmap to tag (B)
Excerpt(4, dddd, ddddd, dddd, dddd) bound via tagmap to tags (B, D)

而我的参数是“B”,我想返回一个摘录ID和描述列表:

[Tag [excerptID=1, description=A], Tag [excerptID=1, description=B], Tag [excerptID=1, description=C], Tag [excerptID=3, description=B], Tag [excerptID=4, description=B], Tag [excerptID=4, description=D]]

到目前为止我有这个

String SQL = "SELECT e.excerptID, t.description from Excerpt AS e LEFT JOIN tagmap AS m ON m.excerptID = e.excerptID LEFT JOIN tag AS t ON t.tagID = m.tagID WHERE t.description = ?";

但这只会返回这个

 [Tag [excerptID=1, description=B], Tag [excerptID=3, description=B], Tag [excerptID=4, description=B]]

我不知道该怎么做。

【问题讨论】:

    标签: mysql sql tags


    【解决方案1】:

    基于 description 参数,我需要返回与绑定到该描述的所有摘录相关的所有标签描述。例如,如果我有四个摘录

    我相信这可以满足您的需求:

    select t.*
    from tags t
    where exists (select 1
                  from tagmap tm1 join
                       tagmap tm2
                       on tm1.excerptid = tm2.excerptid join
                       tags t2
                       on tm2.tagid = t.tagid
                  where tm1.tagid = t.tagid and
                        t2.description = ?
                 );
    

    这看起来很复杂——也许是因为它。但是子查询基本上是将所有标签对附加到同一实体。一个标签(tm2 上的那个)与您关心的描述相关联。那就是where 子句中的t2.description = ?

    另一个与外部表中的标记相关联。那就是关联子句tm1.tagid = t.tagid

    另一种说法是这个查询(基本上是子查询):

    select distinct tm1.tagid
    from tagmap tm1 join
         tagmap tm2
         on tm1.excerptid = tm2.excerptid join
         tags t2
         on tm2.tagid = t.tagid
     where t2.description = ?
    

    返回实体上的所有标签,该实体也具有您要查找的标签。

    【讨论】:

    • 非常感谢!这不是我想要的,但它引导我找到解决方案(在我什至不知道存在子查询之前),所以现在我正在使用这个:“select tm.excerptID, t.description from tagmap as tm left join tag as t on tm.tagID = t.tagID where tm.excerptID in ((select tm1.excerptID from tagmap tm1 join tagmap tm2 on tm1.excerptid = tm2.excerptid join tag t2 on tm2.tagid = t2.tagid where tm1.tagid = t2.tagid 和 t2.description = ?))";它过于复杂但工作正常。
    • @krenkz 。 . .我有点困惑。这回答了您在这里提出的问题。为什么不是你想要的?
    • select t.* from tags t 返回tagIDdescription,但我需要excerptIDdescription(我没有使用表标签(tagID+description)和Java实体标签之间的直接映射(摘录ID+描述)
    • @krenkz 。 . .然后问一个新的问题。这一项明确指出:“我需要返回与绑定到该描述的所有摘录相关的所有标签描述。”这就是这个答案的作用。问题得到解答。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-07-29
    • 1970-01-01
    • 1970-01-01
    • 2015-04-26
    • 2011-03-17
    • 2013-07-22
    • 1970-01-01
    相关资源
    最近更新 更多