我需要将几列连接成一列,每个值之间有空格。问题是当一个值为空时,我最终会在两个值之间出现一个双空格。
例子
SELECT (FIRST_NAME || ' ' || MIDDLE_NAME || ' ' || LAST_NAME
FROM TABLE_A;
如果中间名恰好是 NULL,那么我最终会在名字和姓氏之间有两个空格。有什么办法可以解决这个问题,当有空值时只有一个空格?
我需要将几列连接成一列,每个值之间有空格。问题是当一个值为空时,我最终会在两个值之间出现一个双空格。
例子
SELECT (FIRST_NAME || ' ' || MIDDLE_NAME || ' ' || LAST_NAME
FROM TABLE_A;
如果中间名恰好是 NULL,那么我最终会在名字和姓氏之间有两个空格。有什么办法可以解决这个问题,当有空值时只有一个空格?
SELECT TRIM(TRIM(FIRST_NAME || ' ' || MIDDLE_NAME) || ' ' || LAST_NAME)
FROM TABLE_A;
来自 Oracle 的文档:
CONCAT_WS(分隔符,str1,str2,...)
CONCAT_WS() 代表 Concatenate With Separator,是 CONCAT() 的一种特殊形式。第一个参数是其余参数的分隔符。在要连接的字符串之间添加分隔符。分隔符可以是字符串,其余参数也可以。如果分隔符为 NULL,则结果为 NULL。
还有非常重要的评论:
CONCAT_WS() 不会跳过空字符串。但是,它会跳过分隔符参数之后的任何 NULL 值。
所以在你的情况下应该是:
CONCAT_WS(',', FIRST_NAME, MIDDLE_NAME, LAST_NAME);
with indata as
(
select 'John' as first_name, 'W' as middle_name, 'Smith ' as last_name from dual
union
select null as first_name, null as middle_name, 'Adams' as last_name from dual
union
select 'Tom' as first_name, null as middle_name, 'Jefferson' as last_name from dual
)
select
regexp_replace(trim(indata.first_name || ' ' || indata.middle_name || ' ' || indata.last_name), '\s{2,}', ' ')
from indata;
这就是我通常在 Oracle 中连接多个字段并删除空格的方式:
TRIM(REGEXP_REPLACE(HOUSE_NO || ' ' || PREFIX || ' ' || STREET_NAME || ' ' || STREET_TYPE || ' ' || SUFFIX, ' +', ' '))
您可以使用RPAD()
添加空格字符:
SELECT RPAD(first_name, LENGTH(first_name)+1, ' ')||RPAD(middle_name, LENGTH(middle_name)+1, ' ')||last_name
FROM TABLE_A;
当任何参数为RPAD
NULL 时,结果将为 NULL,并且在 Oracle 中将 NULL 附加到字符串会返回原始字符串。
另一种选择是使用 decode :
SELECT decode(FIRST_NAME,'','',FIRST_NAME ||' ') ||
decode(MIDDLE_NAME,'','',MIDDLE_NAME ||' ') || LAST_NAME
FROM TABLE_A;
或者您可以简单地使用 REPLACE 功能:
with indata as
(select 'John' as first_name, 'W' as middle_name, 'Smith ' as last_name from dual
union
select null as first_name, null as middle_name, 'Adams' as last_name from dual
union
select 'Tom' as first_name, null as middle_name, 'Jefferson' as last_name from dual)
SELECT REPLACE(TRIM(indata.first_name || ' ' || indata.middle_name || ' ' || indata.last_name), ' ', ' ')
FROM indata
(感谢@tbone 提供示例数据:-)
还有一个选择:
SELECT first_name
|| DECODE(middle_name
, NULL, NULL
, ' ' || middle_name)
|| DECODE(last_name
, NULL, NULL
, ' ' || last_name) full_name
FROM table_a
;
不要低估 CASE 语句的简单功能,它可以连接起来。这是一个可以按原样运行的独立示例:
SELECT
CASE WHEN x.FIRST_NAME IS NULL THEN x.FIRST_NAME ELSE x.FIRST_NAME || ' ' END ||
CASE WHEN x.MIDDLE_NAME IS NULL THEN x.MIDDLE_NAME ELSE x.MIDDLE_NAME || ' ' END ||
x.LAST_NAME
FROM (SELECT 'John' AS FIRST_NAME, NULL AS MIDDLE_NAME, 'Doe' AS LAST_NAME FROM DUAL) x;
我有这个例子。希望这可以帮助。只需转到 SQL 服务器,选择新查询和 CP 以下查询:
DECLARE @NULL_SAMLES TABLE
(
NS_ID INT IDENTITY(1,1) PRIMARY KEY CLUSTERED NOT NULL
,COL_01 VARCHAR(10) NULL
,COL_02 VARCHAR(10) NULL
,COL_03 VARCHAR(10) NULL
,COL_04 VARCHAR(10) NULL
)
INSERT INTO @NULL_SAMLES(COL_01,COL_02,COL_03,COL_04)
VALUES
('A','B','C','D')
,(' ' ,'B','C','D')
,(' ',NULL,'C','D')
,('A','B',NULL,'D')
,('A','B','C',NULL)
,(NULL,'B',NULL,'D')
,(NULL,'B','C',NULL)
,('A',NULL,'C',NULL)
,('A',NULL,NULL,'D')
,('A',NULL,NULL,NULL)
,(NULL,'B',NULL,NULL)
,(NULL,NULL,'C',NULL)
,(NULL,NULL,NULL,'D')
SELECT
NS.COL_01
,NS.COL_02
,NS.COL_03
,NS.COL_04,
Stuff(
Coalesce(', ' + nullif(NS.COL_01, ''), '')
+ Coalesce(', ' + nullif(NS.COL_02, ''), '')
+ Coalesce(', ' + nullif(NS.COL_03, ''), '')
+Coalesce(', ' + nullif(NS.COL_04, ''), '')
, 1, 1, '') AS CONC_COLS
FROM @NULL_SAMLES NS