如果STRING_AGG不为空或NULL,则将CONCAT / CONCAT_WS与STRING_AGG一起使用字符串来结果?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如果STRING_AGG不为空或NULL,则将CONCAT / CONCAT_WS与STRING_AGG一起使用字符串来结果?相关的知识,希望对你有一定的参考价值。

我有像这样存储在data列中的JSONB数据:

...,
"cars": [
    { "name":"Ford"},
    { "name":"BMW" },
    { "name":"Fiat"}
  ],
...

还有其他几个属性,它们存储更多的对象数组,但是为了简化我的问题,我只想提及一个。

首先,我想看看是否可以将每个对象的所有名称属性收集到一个字段中。我找到了following question并接受了答案,这使我实现了与以下目标类似的最初目标:

SELECT
    id
  , STRING_AGG(car->>'name', ', ')
FROM
  autos,
  json_array_elements(autos.data->'cars') as car
GROUP BY 1

这将产生一个看起来像这样的字段:

Ford, BMW, Fiat

我的最终目标是能够将所有其他STRING_AGG对象属性连接到一个字段,并在每个字段中都进行简短描述,但是仅当STRING_AGG的结果为NOT EMPTY和NOT NULL时(在我的情况下,最重要的是NOT EMPTY('')。例如,它应如下所示:

...//Cars: Ford, BMW, Fiat //Years: 1991, 1992, 1993 //Model: Mustang, Prius, Chevelle // ... etc., etc.

我曾尝试使用CONCAT和CONCAT_WS,并尝试利用NULLIF,但不确定如何实现所需的内容。特别是,如果有可能在每个STRING_AGG结果前添加一个描述字符串。你能帮忙吗?

答案

Click: step-by-step demo:db<>fiddle

WITH autos AS (
    SELECT '{"cars": [{"name": "BMW", "year": 1991}, {"name": "Ford", "model": "Mustang"}, {"name": "Fiat"}, {"name": "VW", "model": "Golf", "year": 2000}, {"name": "VW", "model": ""}]}'::jsonb as data
)
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",
            "year": 1991
        },
        {
            "name": "Ford",
            "model": "Mustang"
        },
        {
            "name": "Fiat"
        },
        {
            "name": "VW",
            "year": 2000,
            "model": "Golf"
        },
        {
            "name": "VW",
            "model": ""
        }
    ]
}

您可以看到:model没有== nullBMW),year没有FordFiat完全没有数据,VW Golf的所有属性,第二个model为空VW

首先获取所有数据的表:

SELECT 
    car ->> 'name' as name,
    car ->> 'year' as year,
    car ->> 'model' as model
FROM autos,
    jsonb_array_elements(data->'cars') as car

您已经使用了jsonb_array_elements()函数,该函数扩展了JSON数组。 ->>运算符将属性值(在这种情况下为每个数组元素)指定为text

现在,您可以使用model将空值(在这种情况下,将第二个VWNULL标准化为NULLIF())。如果为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_AGG()汇总所有值。提示是,STRING_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

以上是关于如果STRING_AGG不为空或NULL,则将CONCAT / CONCAT_WS与STRING_AGG一起使用字符串来结果?的主要内容,如果未能解决你的问题,请参考以下文章

如何判断int类型为空或null

检查所有三列是不是不为空或为空

在查询SQL语句中为空或不为空怎么写

检查空或 null List<string>

在 Kotlin 中处理可为空或空列表的惯用方式

Vue v-if 语句检查变量是不是为空或 null