PostgreSQL 从多对多关系中将数据作为数组返回

PostgreSQL returning data as an array from a many to many relationship

我正在寻找存储和检索数据数组的最佳方式。我目前正在实施的解决方案使用如下多对多关系。

venue_themes

user_id  style  environment
A1A2     formal  indoor
A2B2     formal  outdoor

theme_setting_to_setting_enum

id  user_id  setting_enum_id
1   A1A2       1
2   A1A2       3 
3   A2B2       1 
4   A2B2       2

setting_enum

id  value
1   garden
2   beach
3   golf course
4   backyard

我目前的查询是:

SELECT vt.user_id, vt.style, vt.environment, se.value FROM venue_themes vt JOIN theme_settings_to_setting_enum ts ON vt.user_id = ts.user_id JOIN setting_enum se ON ts.setting_enum_id = se.id GROUP BY vt.user_id, ts.id, se.id;

这有效,但它 return 多行具有与我设置的枚举值不同的相同数据。

一个例子 return 是:

user_id    style    environment   value
AAAA       formal   indoor        beach
AAAA       formal   indoor        backyard
AAAA       formal   indoor        tent

这很好,但如果我有很多值,这似乎太过分了。我真正希望我的数据看起来像:

user_id    style    environment   value
AAAA       formal   indoor        beach, backyard, tent

理想情况下,我会将我的值 returned 放入数组或类似的东西中,这样我就不必构建函数来操作 returned 数据。

您可以从 GROUP BY 子句中删除 se.id,并使用 STRING_AGG() 生成 CSV 字符串:

SELECT vt.user_id, vt.style, vt.environment, STRING_AGG(se.value, ', ') se_values
FROM venue_themes vt 
JOIN theme_settings_to_setting_enum ts ON vt.user_id = ts.user_id 
JOIN setting_enum se ON ts.setting_enum_id = se.id 
GROUP BY vt.user_id;

假设user_idvenue_themes的主键,在GROUP BY子句中只有这一列就足够了(table的其他列是功能上依赖于主键)。

您可以使用 ORDER BY 子句控制值在字符串中的聚合顺序:

STRING_AGG(se.value, ', ' ORDER BY se.id) se_values

如果您想要一个数组而不是 CSV 字符串,请使用 ARRAY_AGG():

ARRAY_AGG(se.value, ', ' ORDER BY se.id) se_values