@
dawniii 这种情况不叫一对多,叫多对多。
一对多应该把表做成这样,不需要中间表。
article(id, ...)
tag(id, name, article_id)
author(id, name, article_id)
这种全用中间表不带冗余字段的设计,是符合关系型数据库范式的表结构,在这种表结构上当然要用 JOIN 。
不用 JOIN 的话表就不这么设计了,比如用 PostgreSQL 的 JSONB 数组来存 tag,直接放在 article 表里面,建一个 GIN 索引。
即使是这样的表结构,不用 JOIN 当然是可以查的,只不过比用 JOIN 慢。
SELECT id FROM tag WHERE name = XXX 取出 tag_id
SELECT article_id FROM article_tag WHERE tag_id = xxx 取出 article_tag_ids
SELECT id FROM user WHERE name = XXX 取出 user_id
SELECT article_id FROM article_author WHERE author_id = xxx 取出 article_author_ids
SELECT * FROM article WHERE id IN(article_ids1) AND id IN (article_ids2)
但是,
前两个 SQL 合并成 SELECT article_id FROM tag INNER JOIN article_tag ON tag_id = id WHERE name = xxx 当然会比查两次要快。因为这个 JOIN 没有带来额外的开销。我觉得即使是 MySQL 也能正确地执行这句 SQL
后面两条也一样。
如果全都合在一起,
SELECT article.* FROM article
INNER JOIN article_tag ON
article.id = article_tag.article_id
INNER JOIN tag ON
tag.id = article_tag.tag_id
INNER JOIN article_author ON
article.id = article_author.article_id
INNER JOIN author ON
author.id = article_author.author_id
WHERE
tag.name = xxx AND
author.name = yyy
GROUP BY
article.id这个 SQL 也没什么问题,JOIN 仍然没有引入额外的开销,而且还比上面那 5 句好懂。
但如果用的数据库是 MySQL,这个 SQL 很有可能被用奇怪的方式来执行,那当然就慢了。
这就是很多人说不能用 JOIN 的理由。