Sql Oracle使用可选字段和重复值格式化csv地址

Sql Oracle使用可选字段和重复值格式化csv地址,sql,regex,oracle,Sql,Regex,Oracle,我有一个Oracle PLSQL函数,它以逗号分隔的格式返回地址(从sql调用),例如: , 7 Hawaii Street, Windhoek, Windhoek, 9000, , , , , 地址以多种不同的样式存储,因此字段可能为空(例如,如果此人不住在公寓中,则地址行1也可能为空) 每个字段前还有一个可选的前导空格 我想以以下格式打印输出,中间不留空行 7 Hawaii Street,Windhoek,Windhoek,9000 甚至 7 Hawaii Street,Windhoe

我有一个Oracle PLSQL函数,它以逗号分隔的格式返回地址(从sql调用),例如:

, 7 Hawaii Street, Windhoek, Windhoek, 9000, , , , , 
地址以多种不同的样式存储,因此字段可能为空(例如,如果此人不住在公寓中,则地址行1也可能为空)

每个字段前还有一个可选的前导空格

我想以以下格式打印输出,中间不留空行

7 Hawaii Street,Windhoek,Windhoek,9000
甚至

7 Hawaii Street,Windhoek,9000
我的尝试如下(删除每个字段前的空格并删除两个逗号;但完全丢失温得和克):

有人能帮我修理一下,这样它就不会松开温得和克吗?

试试这个

WITH t AS 
    (SELECT LEVEL AS Item_no, TRIM(REGEXP_SUBSTR(', 7 Hawaii Street, Windhoek, Windhoek, 9000, , , , , ', '[^,]+', 1, LEVEL)) AS item 
    FROM dual
    CONNECT BY REGEXP_SUBSTR(', 7 Hawaii Street, Windhoek, Windhoek, 9000, , , , , ', '[^,]+', 1, LEVEL) IS NOT NULL)
SELECT listagg(item, ',') WITHIN GROUP (ORDER BY Item_no)
FROM t
WHERE item IS NOT NULL;
输出

7 Hawaii Street,Windhoek,Windhoek,9000
WITH addresses ( address ) AS (
  SELECT ', 7 Hawaii Street, Windhoek, Windhoek, Windhoek County, Windhoek County, 9000, , , , , ' FROM DUAL
)
SELECT LISTAGG( address_part, ',' ) WITHIN GROUP ( ORDER BY lvl ) AS address
FROM   (
  SELECT ID,
         ROW_NUMBER() OVER ( PARTITION BY id ORDER BY ROWNUM ) AS lvl,
         t.column_value AS address_part,
         CASE WHEN LAG( t.column_value ) OVER ( PARTITION BY id ORDER BY ROWNUM )
                   = t.column_value THEN 1 ELSE 0 END AS is_duplicate
  FROM   ( SELECT ROWID AS id,
                  REGEXP_REPLACE(
                    REGEXP_REPLACE( address, '\s*,\s*', ',' ),
                    '^,+|,+$|(,),+',
                    '\1'
                  ) AS address
           FROM   addresses
         ) a
         CROSS JOIN
         TABLE(
           CAST(
             MULTISET(
               SELECT REGEXP_SUBSTR( a.address, '[^,]+', 1, LEVEL )
               FROM   DUAL
               CONNECT BY LEVEL <= REGEXP_COUNT( a.address, '[^,]+' )
             ) AS SYS.ODCIVARCHAR2LIST
           )
         ) t
)
WHERE  is_duplicate = 0
GROUP BY id;
ADDRESS
---------------------------------------------
7 Hawaii Street,Windhoek,Windhoek County,9000
消除重复项

7 Hawaii Street,Windhoek,Windhoek,9000
WITH addresses ( address ) AS (
  SELECT ', 7 Hawaii Street, Windhoek, Windhoek, Windhoek County, Windhoek County, 9000, , , , , ' FROM DUAL
)
SELECT LISTAGG( address_part, ',' ) WITHIN GROUP ( ORDER BY lvl ) AS address
FROM   (
  SELECT ID,
         ROW_NUMBER() OVER ( PARTITION BY id ORDER BY ROWNUM ) AS lvl,
         t.column_value AS address_part,
         CASE WHEN LAG( t.column_value ) OVER ( PARTITION BY id ORDER BY ROWNUM )
                   = t.column_value THEN 1 ELSE 0 END AS is_duplicate
  FROM   ( SELECT ROWID AS id,
                  REGEXP_REPLACE(
                    REGEXP_REPLACE( address, '\s*,\s*', ',' ),
                    '^,+|,+$|(,),+',
                    '\1'
                  ) AS address
           FROM   addresses
         ) a
         CROSS JOIN
         TABLE(
           CAST(
             MULTISET(
               SELECT REGEXP_SUBSTR( a.address, '[^,]+', 1, LEVEL )
               FROM   DUAL
               CONNECT BY LEVEL <= REGEXP_COUNT( a.address, '[^,]+' )
             ) AS SYS.ODCIVARCHAR2LIST
           )
         ) t
)
WHERE  is_duplicate = 0
GROUP BY id;
ADDRESS
---------------------------------------------
7 Hawaii Street,Windhoek,Windhoek County,9000
这应该起作用:

trim( ',' from regexp_replace(str, '(,\s*)+', ','))
它将每次出现的(一个或多个逗号,每个后跟零个或多个空格)替换为一个逗号。然后它会修剪前导和尾随逗号(如果有)


话虽如此,正如我在评论中提到的,字符串很可能是从基础数据开始构建的首先构建字符串是应该修复的,那么您就不会有这个问题。

数据库中的数据首先是如何存储的?如果它存储在单独的列中,并且字符串是在传递给PL/SQL函数之前生成的,请首先更改生成逗号分隔字符串的代码。看起来您的DB使用单个空格作为NULL的占位符(替换),然后您使用LISTAGG或类似的。。。这可以从源头上解决<因为
listag()
忽略空值,所以不需要使用code>where item not null。