如何在没有NULL结果的情况下合并值(Snowflake)

时间:2020-05-22 22:00:37

标签: sql string concat snowflake-cloud-data-platform

我正在尝试在雪花中连接非空值。

我当前的代码:

            CONCAT(
                CASE WHEN Red='TRUE' THEN 'Red, ' ELSE '' END ||
                CASE WHEN Blue='TRUE' THEN 'Blue, ' ELSE '' END ||
                CASE WHEN Black='TRUE' THEN 'Black, ' ELSE '' END ||
                CASE WHEN White='TRUE' THEN 'White, ' ELSE '' END)

Return: 
Red, White, Black,
Black,
...

Want:
Red, White, Black
Black

在Mysql中,我将使用Concat_WS,但在Snowflake中,如果一个值为NULL,则返回NULL:

            CONCAT_WS(', ',
                CASE WHEN Red='TRUE' THEN 'Red' ELSE NULL END,
                CASE WHEN Blue='TRUE' THEN 'Blue' ELSE NULL END,
                CASE WHEN Black='TRUE' THEN 'Black' ELSE NULL END,
                CASE WHEN White='TRUE' THEN 'White' ELSE NULL END)

3 个答案:

答案 0 :(得分:2)

有点晚了,但我遇到了同样的问题并找到了不同的解决方案:

正如在 CONCATWS_CONCAT 之前正确指出的那样,当它们的任何参数为 NULL 时,它们总是返回 NULL

但是,由于 Snowflake 有 ARRAY 的概念(即支持半结构化数据),即我们可以执行以下操作:

  1. 使用 array_construct 将原始值收集到一个数组中
  2. 使用 NULL 从数组中删除 array_compact
  3. 使用 array_to_string 将剩余的数组项连接成一个字符串

这是修改代码,使用数组:

select array_to_string(array_compact(array_construct( 
          CASE WHEN Red = 'TRUE' THEN 'Red' ELSE NULL  END,
          CASE WHEN Blue = 'TRUE' THEN 'Blue' ELSE NULL END, 
          CASE WHEN Black = 'TRUE' THEN 'Black' ELSE NULL END,
          CASE WHEN White = 'TRUE' THEN 'White' ELSE NULL END)), ', ') as result
FROM values 
( true, true, false, false ),
( true, false, false, true ),
( false, false, true, false ),
( false, true, false, true ),
( true, true, true, true )
v(red,blue,black,white);

编辑:您也可以使用 array_construct_compact,它是 array_constructarray_compact

的精简版本

答案 1 :(得分:1)

您可以使用RTRIM删除结尾的逗号:

select RTRIM(CONCAT( 
          CASE WHEN Red = 'TRUE' THEN 'Red, ' ELSE ''  END,
          CASE WHEN Blue = 'TRUE' THEN 'Blue, ' ELSE '' END, 
          CASE WHEN Black = 'TRUE' THEN 'Black, ' ELSE '' END,
          CASE WHEN White = 'TRUE' THEN 'White, ' ELSE '' END ),', ' ) result
FROM values 
( true, true, false, false ),
( true, false, false, true ),
( false, false, true, false ),
( false, true, false, true ),
( true, true, true, true )
v(red,blue,black,white);

+-------------------------+
| RESULT                  |
+-------------------------+
| Red, Blue               |
| Red, White              |
| Black                   |
| Blue, White             |
| Red, Blue, Black, White |
+-------------------------+

您还可以考虑使用NULLIF函数将空字符串转换为NULL:

select NULLIF( RTRIM(CONCAT( 
          CASE WHEN Red = 'TRUE' THEN 'Red, ' ELSE ''  END,
          CASE WHEN Blue = 'TRUE' THEN 'Blue, ' ELSE '' END, 
          CASE WHEN Black = 'TRUE' THEN 'Black, ' ELSE '' END,
          CASE WHEN White = 'TRUE' THEN 'White, ' ELSE '' END ),', ' ), '' )result
FROM values 
( false, false, false, false )
v(red,blue,black,white);

答案 2 :(得分:0)

我知道您的表达式可以满足您的要求,但是您需要删除结尾的逗号。您可以为此使用TRIM()

TRIM(', ' FROM 
       CASE WHEN Red   = 'TRUE' THEN 'Red, '   ELSE '' END  
    || CASE WHEN Blue  = 'TRUE' THEN 'Blue '   ELSE '' END 
    || CASE WHEN Black = 'TRUE' THEN 'Black, ' ELSE '' END 
    || CASE WHEN White = 'TRUE' THEN 'White, ' ELSE '' END
)

请注意,同时使用 ||CONCAT()都是没有意义的:我删除了周围的CONCAT()