Arrays 如果String\u AGG不为空或NULL,则使用CONCAT/CONCAT\u WS和String\u AGG结果预先结束字符串?
我将JSONB数据存储在数据列中,如下所示:Arrays 如果String\u AGG不为空或NULL,则使用CONCAT/CONCAT\u WS和String\u AGG结果预先结束字符串?,arrays,postgresql,object,concatenation,jsonb,Arrays,Postgresql,Object,Concatenation,Jsonb,我将JSONB数据存储在数据列中,如下所示: ... "dealers": [ { "dealership":"LHM"}, { "dealership”:"Camp"}, { "dealership":"HMA"} ], "cars": [ { "name":"Ford"}, { "name":"BMW" }, { "name":"Fiat"} ], ... 还有几个属性存储多个对象数组,但是为了简化我的问题,我只想提到这两个 首先,
...
"dealers": [
{ "dealership":"LHM"},
{ "dealership”:"Camp"},
{ "dealership":"HMA"}
],
"cars": [
{ "name":"Ford"},
{ "name":"BMW" },
{ "name":"Fiat"}
],
...
还有几个属性存储多个对象数组,但是为了简化我的问题,我只想提到这两个
首先,我想看看是否可以将每个对象的所有名称属性收集到一个字段中。我找到并接受了答案,这让我达到了最初的目标,做了类似于以下的事情:
SELECT
id
, STRING_AGG(car->>'name', ', ')
FROM
autos,
json_array_elements(autos.data->'cars') as car
GROUP BY 1
这将生成一个如下所示的字段:
Ford, BMW, Fiat
...//Cars: Ford, BMW, Fiat //Dealerships: LMH, Camp, HMA //... // etc.
现在,我的最终目标是能够将多个对象数组中的所有其他STRING_AGG对象属性连接到一个字段中,并对每个属性进行简要说明,但前提是STRING_AGG的结果不为空且不为NULL(在我的情况下最重要的是不为空(“”)。例如,它应该如下所示:
Ford, BMW, Fiat
...//Cars: Ford, BMW, Fiat //Dealerships: LMH, Camp, HMA //... // etc.
我曾尝试使用CONCAT和CONCAT_WS,并尝试使用NULLIF,但不确定如何实现我想要的。特别是,如果可以在每个字符串_AGG结果前添加一个描述字符串。您能提供帮助吗
最新消息:我能够在CONCAT中找到如何使用案例陈述来实现这一点,但我现在想知道这是否是一个好方法,或者是否可以用与S-Man给出的答案类似的方法来实现。谢谢。
使用此数据集:
{
"cars": [
{
"name": "BMW",
"year": 1991
},
{
"name": "Ford",
"model": "Mustang"
},
{
"name": "Fiat"
},
{
"name": "VW",
"year": 2000,
"model": "Golf"
},
{
"name": "VW",
"model": ""
}
]
}
您可以看到:BMW
没有车型
(==null
),福特没有年份
,菲亚特没有数据
,大众高尔夫的所有属性,第二款大众车型
为空
首先获取所有数据的表:
SELECT
car ->> 'name' as name,
car ->> 'year' as year,
car ->> 'model' as model
FROM autos,
jsonb_array_elements(data->'cars') as car
您已经使用了扩展JSON数组的jsonb\u array\u elements()
函数。->
运算符将属性值(在本例中为每个数组元素)作为文本提供
现在,您可以使用NULLIF()
将空值(model
第二个VW
,在本例中)规范化为NULL
。如果值为空,您可以将值设置为NULL
:
NULLIF(myvalue, '')
这将导致您:
SELECT
NULLIF(car ->> 'name', '') as name,
NULLIF(car ->> 'year', '') as year,
NULLIF(car ->> 'model', '') as model
FROM autos,
jsonb_array_elements(data->'cars') as car
现在您不再有空值,而是有许多NULL
值
现在,您可以使用STRING\u AGG()
按预期聚合所有值。线索是,STRING\u AGG()
自动忽略NULL
值,因此您无需犹豫
SELECT
STRING_AGG(NULLIF(car ->> 'name', ''), ',') as names,
STRING_AGG(NULLIF(car ->> 'year', ''), ',') as years,
STRING_AGG(NULLIF(car ->> 'model', ''), ',') as models
FROM autos,
jsonb_array_elements(data->'cars') as car
现在,您只有三列和一行。每个值都聚合到一个字符串中
最后,您希望将它们链接成一个字符串。为此,您可以使用CONCAT()
或运算符|
:
SELECT
'Cars: ' || STRING_AGG(NULLIF(car ->> 'name', ''), ',') || ' // '
'Years: ' || STRING_AGG(NULLIF(car ->> 'year', ''), ',') || ' // '
'Models: ' || STRING_AGG(NULLIF(car ->> 'model', ''), ',')
FROM autos,
jsonb_array_elements(data->'cars') as car
编辑:
澄清数据:
{
"cars": [
{
"name": "BMW"
},
{
"name": "Ford"
},
{
"name": "Fiat"
}
],
"dealers": [
{
"dealership": "LHM"
},
{
"dealership": "Camp"
},
{
"dealership": "HMA"
}
]
}
点击:
在这种情况下,您必须在加入之前扩展和聚合数组
在上面的相关列中运行。我今天确实解决了这个问题,非常感谢您的帮助。不过我想我应该更好地解释我的问题。您的方法非常方便,但是如果您有多个对象数组,希望将其连接到一个字段中,类似于您在回答中使用了链接方法吗?类似的方法可行吗?请提供一个示例(为此,请编辑您的问题)没问题。我更新了我的问题。这更清楚了吗,还是你需要更多的清晰/详细信息?在这种情况下,你必须在加入之前扩展和合并阵列。根据这一点,可以这样做:;编辑答案谢谢你花时间解决这个问题。我将你的答案标记为正确。我最终做了一些类似的事情与你告诉我的有点不同。最终,你的回答和后续建议起了作用!谢谢。