Reputation: 57
I have a ton of columns I am trying to aggregate together and most of them have NULL values. I want to separate values that do appear with a ';' but I cannot find an effective way to do this in oracle. CONCAT_WS would be exactly what I need as it would not add the delimeter between NULL values, but oracle does not support this.
concat_ws(';','dx89','dx90','dx91','dx92') as diagnoses3
ORA-00904: "CONCAT_WS": invalid identifier
Using a function like this is similar but doesn't quite get me what I need as you can see the ';' on the end of the string since dx91 and dx92 are NULL values:
dx89||';'||dx90||';'||dx91||';'||dx92 as diagnoses2
I63.8;I63.9;;
Any help would be greatly appreciated!
Upvotes: 3
Views: 8524
Reputation: 167832
You can use a CASE
expression to concatenate only the non-NULL
values with leading delimiters and then remove only the initial delimiter:
SELECT SUBSTR(
CASE WHEN dx89 IS NOT NULL THEN ';'||dx89 END
|| CASE WHEN dx90 IS NOT NULL THEN ';'||dx90 END
|| CASE WHEN dx91 IS NOT NULL THEN ';'||dx91 END
|| CASE WHEN dx92 IS NOT NULL THEN ';'||dx92 END,
2
) AS diagnoses2
FROM table_name;
or
SELECT SUBSTR(
NVL2(dx89, ';'||dx89, NULL)
|| NVL2(dx90, ';'||dx90, NULL)
|| NVL2(dx91, ';'||dx91, NULL)
|| NVL2(dx92, ';'||dx92, NULL),
2
) AS diagnoses2
FROM table_name;
Which, for the sample data:
CREATE TABLE table_name(dx89, dx90, dx91, dx92) AS
SELECT 'A', 'B', NULL, 'D' FROM DUAL UNION ALL
SELECT NULL, NULL, 'C', NULL FROM DUAL UNION ALL
SELECT 'A', 'B', 'C', 'D' FROM DUAL UNION ALL
SELECT ';;', NULL, NULL, NULL FROM DUAL
Both output:
DIAGNOSES2 |
---|
A;B;D |
C |
A;B;C;D |
;; |
If, instead of using SUBSTR
, you use TRIM
and the first non-NULL
value has the delimiter character as the first character(s) in the string then you will remove too many characters and the final row of the sample data would output NULL
. Instead, it is better to remove only the number of characters in the delimiter using SUBSTR
.
Upvotes: 0
Reputation: 65218
You can use NVL2()
function specific to Oracle DB together with pipe concatenation operators :
SELECT TRIM(LEADING ';'
FROM dx89||NVL2(dx90,';'||dx90,dx90)||
NVL2(dx91,';'||dx91,dx91)||
NVL2(dx92,';'||dx92,dx92)) AS "Concatenated String"
FROM t
Upvotes: 3