MySQL:具有两个多对多关系和重复项的查询

MySQL:具有两个多对多关系和重复项的查询,mysql,sql,duplicates,inner-join,Mysql,Sql,Duplicates,Inner Join,我有四种模式:文章,作者和标签。每篇文章可以有许多作者,也可以有许多标记 因此,我的数据库将有以下表格: `article` `article_author` `author` `article_tag` `tags` 在MySQL中: DROP TABLE IF EXISTS article_tag; DROP TABLE IF EXISTS article_author; DROP TABLE IF EXISTS author; DROP TABLE IF EXISTS tag; DROP

我有四种模式:
文章
作者
标签
。每篇文章可以有许多作者,也可以有许多标记

因此,我的数据库将有以下表格:

`article`
`article_author`
`author`
`article_tag`
`tags`
在MySQL中:

DROP TABLE IF EXISTS article_tag;
DROP TABLE IF EXISTS article_author;
DROP TABLE IF EXISTS author;
DROP TABLE IF EXISTS tag;
DROP TABLE IF EXISTS article;

CREATE TABLE IF NOT EXISTS author (
  id INT(11) NOT NULL AUTO_INCREMENT,
  name VARCHAR(255),
  PRIMARY KEY (id)
);

CREATE TABLE IF NOT EXISTS article (
  id INT(11) NOT NULL AUTO_INCREMENT,
  title VARCHAR(255),
  PRIMARY KEY (id)
);

CREATE TABLE IF NOT EXISTS tag (
  id INT(11) NOT NULL AUTO_INCREMENT,
  tag VARCHAR(255),
  PRIMARY KEY (id)
);

CREATE TABLE IF NOT EXISTS article_author (
  article_id INT(11) NOT NULL,
  author_id INT(11) NOT NULL,
  PRIMARY KEY (article_id, author_id),
  INDEX fk_article_author_article_idx (article_id ASC) VISIBLE,
  INDEX fk_article_author_author_idx (author_id ASC) VISIBLE,
  CONSTRAINT fk_article_author_article
    FOREIGN KEY (article_id)
    REFERENCES article (id),
  CONSTRAINT fk_article_author_author
    FOREIGN KEY (author_id)
    REFERENCES author (id)
);

CREATE TABLE IF NOT EXISTS article_tag (
  article_id INT(11) NOT NULL,
  tag_id INT(11) NOT NULL,
  PRIMARY KEY (article_id, tag_id),
  INDEX fk_article_tag_article_idx (article_id ASC) VISIBLE,
  INDEX fk_article_tag_tag_idx (tag_id ASC) VISIBLE,
  CONSTRAINT fk_article_tag_article
    FOREIGN KEY (article_id)
    REFERENCES article (id),
  CONSTRAINT fk_article_tag_tag
    FOREIGN KEY (tag_id)
    REFERENCES tag (id)
);
我们可以在数据库中插入一些数据:

INSERT INTO article (id, title) VALUES (1, 'first article'), (2, 'second article'), (3, 'third article');
INSERT INTO author (id, name) VALUES (1, 'first author'), (2, 'second author'), (3, 'third author'), (4, 'fourth author');
INSERT INTO tag (id, tag) VALUES (1, 'first tag'), (2, 'second tag'), (3, 'third tag'), (4, 'fourth tag'), (5, 'fifth tag');
INSERT INTO article_tag (article_id, tag_id) VALUES (1, 1), (1, 2), (1, 3), (2, 2), (2, 4), (2, 5), (3, 1), (3, 2);
INSERT INTO article_author (article_id, author_id) VALUES (1, 1), (1, 2), (1, 3), (2, 2), (2, 4), (3, 1), (3, 2), (3, 3), (3, 4);
现在我想要检索文章,对于每一篇文章,我想要相关的作者ID和标签ID:

SELECT 
  article.id, 
  article.title,
  JSON_ARRAYAGG(author.id) AS authors,
  JSON_ARRAYAGG(tag.id) AS tags
FROM article
INNER JOIN article_author ON article.id = article_author.article_id
INNER JOIN author ON article_author.author_id = author.id
INNER JOIN article_tag ON article.id = article_tag.article_id
INNER JOIN tag ON article_tag.tag_id = tag.id
GROUP BY article.id;
这是返回的副本。不是由于
JSON_ARRAYAGG
(我们可以替换if to
COUNT
,重复项仍然存在),而是由于同一查询中的双重关系:如果我们从查询中删除标记或作者,重复项将消失。但我真的希望能够在同一个查询中查询多个关系


如何避免这些重复项?

我怀疑您指的是JSON字段中的重复项。问题是你沿着两个不同的维度连接,所以你得到了每一篇文章的笛卡尔积

使用一些聚合函数,您只需使用
DISTINCT
即可解决此问题。该选项不适用于JSON函数。相反,您可以使用子查询:

SELECT a.id, a.title,
       (SELECT JSON_ARRAYAGG(aa.author_id)
        FROM article_author aa 
        WHERE a.id = aa.article_id 
       ) as authors,
       (SELECT JSON_ARRAYAGG(art.tag_id)
        FROM article_tag art
        WHERE a.id = art.article_id 
       ) as tags
FROM article a;
请注意,因为您只包含ID,所以不需要连接到基表--
authors
标记
。当然,如果您愿意,可以在子查询中这样做,但这是不必要的


是一个Dfiddle。

问得好,但你应该回答这个问题,并用表格文本形式的样本数据添加你想要的结果。我看不到重复项:。@GordonLinoff重复项在author数组和tags数组中,我明白了……如果我想检索ID之外的其他字段,该怎么办?我刚刚尝试将JSON_ArrayAg与JSON_对象一起使用,但正如您所说,我们没有其他可用字段。我将在另一个问题中提出这个问题,因为这是正确的