连接两个表并从一列返回多个匹配项的 SQL 查询?
Posted
技术标签:
【中文标题】连接两个表并从一列返回多个匹配项的 SQL 查询?【英文标题】:SQL query that joins two tables and returns multiple matches from one column? 【发布时间】:2013-02-18 01:03:27 【问题描述】:我的标题很糟糕,这可能就是我在 Google 上找不到我想要的东西的原因。
我想要做的是从一个旧的内部博客中导出一些数据,以便我可以将其导入到其他内容中。我的问题是,虽然我可以创建我正在寻找的那种 JOIN,但第二个表中的匹配项可以包含多行,所以我最终会得到大量重复数据。我需要从第二个表中获取结果并将这些(如果有多个匹配项)连接到查询结果中的单个字段中。查询不需要 WHERE 约束,我正在尝试检索整个 blog_posts 表。
希望这个表格结构的缩写布局有助于说明:
blog_posts blog_categories
---------------------------------------
post_id post_id
post_content category_id
post_author
这里有一些示例数据。
blog_posts 表数据:
post_id post_content post_author
----------------------------------
1 foo1 bob
2 foo2 bob
3 foo3 fred
blog_categories 表数据:
post_id category_id
--------------------
1 1
1 2
1 6
2 1
3 2
3 4
而我理想的结果应该是这样的:
post_id post_content post_author category_ids
------------------------------------------------
1 foo1 bob 1,2,6
2 foo2 bob 1
3 foo3 fred 2,4
我能得到的最接近的是这样的简单连接:
SELECT
blog_posts.post_id,
blog_posts.post_content,
blog_posts.post_author,
blog_categories.category_id
FROM blog_posts
INNER JOIN blog_categories
ON blog_posts.post_id = blog_categories.post_id
但这会多次返回 blog_posts 表中的匹配项(每个匹配的 category_id 一次)。
有什么方法可以只使用 SQL 来完成我想要的吗?我在想某种子选择会起作用,但是我无法理解它是如何工作的 - 我知道我基本上想在我的“循环”中使用类别 ID 进行选择当前的帖子 id,但它的语法让我无法理解。它不需要高效,这是一次性操作。
【问题讨论】:
【参考方案1】:group_concat()
函数完全符合您的需要:
SELECT
blog_posts.post_id,
blog_posts.post_content,
blog_posts.post_author,
group_concat(blog_categories.category_id)
FROM blog_posts
JOIN blog_categories ON blog_posts.post_id = blog_categories.post_id
GROUP BY 1, 2, 3
【讨论】:
@BenjaminM 是的 - 这是一个 mysql 唯一的功能,但问题是 mysql 问题是mysql,因为我把它做成了mysql ;) 我在看这个,虽然 BLOB 输出给我带来了导出问题,但它似乎有效。我一点也不明白它是如何工作的,尤其是最后的“GROUP BY”。那些是 category_id 的还是 post_id 的?我有大约 420 个 post_id 行和 40 个 category_id 行 - 我希望我的“GROUP BY”实际上不需要列出每一个。 此外,如果我在查询末尾使用GROUP BY blog_posts.post_id, blog_posts.post_content, blog_posts.post_author
,它似乎确实有效。我抽查了一些数据,看起来不错。甚至添加了另一个 JOIN 以便我可以从另一个表中提取类别名称。
@sporker SQL 标准允许通过它们的 position 引用分组列,而不是它们的 expession。这在我们计算较长的列时特别方便,但我觉得简洁令人愉悦。避免使用这种语法,但我接受它。【参考方案2】:
你想GROUP BY blog_posts.post_id, blog_posts.post_content, blog_posts.post_author
。然后使用aggregate function
(http://en.wikipedia.org/wiki/Aggregate_function) 从每个组中获取所有blog_categories.category_id
值并将其转换为单个字符串。
您使用的是哪个 DBMS?对于 Postgres,您可以简单地使用数组作为聚合函数:
SELECT
blog_posts.post_id,
blog_posts.post_content,
blog_posts.post_author,
ARRAY_AGG(blog_categories.category_id)
FROM blog_posts
INNER JOIN blog_categories ON blog_posts.post_id = blog_categories.post_id
GROUP BY
blog_posts.post_id,
blog_posts.post_content,
blog_posts.post_author
或者使用ARRAY_TO_STRING(ARRAY_AGG(blog_categories.category_id), ',')
得到一个逗号分隔的字符串。
【讨论】:
仅作记录,这是 MySQL。 对不起。不过,从好的方面来说,我使用 PostgreSQL 比使用 MySQL 更频繁,所以我已将您的答案添加到我的本地笔记列表中。以上是关于连接两个表并从一列返回多个匹配项的 SQL 查询?的主要内容,如果未能解决你的问题,请参考以下文章