Remove substring within aggregate - sql

I am working in a data warehouse and combining 3 columns with the following:
CAST(
ISNULL(PORCH_TYPE_1,'') ||
CASE WHEN PORCH_TYPE_2 IS NULL THEN '' ELSE ', ' END ||
ISNULL(PORCH_TYPE_2,'') ||
CASE WHEN PORCH_TYPE_3 IS NULL THEN '' ELSE ', ' END ||
ISNULL(PORCH_TYPE_3,'') AS VARCHAR(250)
) AS PORCH_TYPE,
This is working, except in the results, I can end up with something that looks like:
Open Porch, None, None
or
None, None, Open Porch
What I'm needing to do is remove both
None
and
,None
How would I go about doing that within this same column/statement?

One method is to concatenate the comma to the end of each valid porch type. Then remove the final trailing comma using TRIM():
TRIM(TRAILING ',' FROM
((CASE WHEN PORCH_TYPE_1 <> 'None' THEN PORCH_TYPE_1 || ',' END) ||
(CASE WHEN PORCH_TYPE_2 <> 'None' THEN PORCH_TYPE_2 || ',' END) ||
(CASE WHEN PORCH_TYPE_3 <> 'None' THEN PORCH_TYPE_3 || ',' END)
)

Related

How to concatenate multiple columns where value may be be NULL

I need to pull a query from multiple columns from a table. Some rows will have data in one column, others will have two, three, and even four.
I tried to use this construct:
SELECT person_uid,('(' || major || NVL((',' ||second_major), '') || NVL((',' ||third_major), '') || NVL(',' ||fourth_major, '') || ')' ) AS MAJORS FROM academic_study
But the result would be like this:
6231 (BUMG,BUMK,,)
19091 (TDST,TDPG,,)
I need the parentheses, but not the trailing commas.
I could potentially strip out the extra commas in post processing, but I would prefer to do it in the SQL. I am using ORACLE.
You should fix your data model! Storing multiple columns with parallel data is awkward.
One method is:
select person_uid,
( '(' || major ||
(case when second_major is not null then ',' || second_major end) ||
(case when third_major is not null then ',' || third_major end) ||
(case when fourth_major is not null then ',' || fourth_major end) ||
')'
)

How can combine the values of multiple columns to a single comma separated column in Oracle SQL?

I need to create a column that has all the values from the previous columns combined and separated using commas ', '
I can't use listagg since I'm trying to combine multiple columns instead of rows.
below is an example of how the result column should look like, thanks.
Use string concatenation:
select trim(leading ',' from
(case when column1 is not null then ',' || column1 end) ||
(case when column2 is not null then ',' || column2 end) ||
(case when column3 is not null then ',' || column3 end)
)
This is also using a string concatenation but slightly different
SELECT
SUBSTR(
REPLACE(
', ' || NVL(column1,'!!') || ', ' || NVL(column2,'!!') || ', ' || NVL(column3,'!!')
,', !!','')
,3,100)

Converting a numerical code into a word string right-to-left

I am trying to use an SQL select expression to convert the following from 1st column, into the 2nd.
Code Outcome
88881133 Species 1, 2, 3, 4 sick
88888888 NULL
88888833 Species 1, 2 sick
88888811 Species 1, 2 sick
88888111 Species 1, 2, 3 sick
88888881 Species 1 sick
Code should be read from right to left.
1 or 3 means that the Species is sick.
8 means Species is not sick.
I suppose it involves some CASE expression, but I couldn't go very further than:
SELECT
CASE WHEN RIGHT(Code, 1) = 1 OR WHEN RIGHT(Code, 1) = 3
THEN 'Species 1 sick' END AS Outcome
FROM table
I use the Vertica database
Here is another method just using like and case. I'm just translating 1 and 3 to 1, and 8 to 0. Mostly because I was going to do a binary method but this seemed simpler. The real reason is just to keep the case statement simple (else you have to check both 1 and 3 cases).
The rtrim has a second parameter meaning to trim only that extra comma space. It's a simple trick to remove the last one. The outer case is just making sure there are species (otherwise it'll return null).
Hope it helps.
with translated_mytable as (
select code, translate(code,'813','011') newcode
from mytable
)
select Code,
case when newcode like '%1%' then
'Species ' ||
rtrim(case when newcode like '_______1' then '1, ' else '' end ||
case when newcode like '______1_' then '2, ' else '' end ||
case when newcode like '_____1__' then '3, ' else '' end ||
case when newcode like '___ 1___' then '4, ' else '' end ||
case when newcode like '___1____' then '5, ' else '' end ||
case when newcode like '__1_____' then '6, ' else '' end ||
case when newcode like '_1______' then '7, ' else '' end ||
case when newcode like '1_______' then '8, ' else '' end,
', ') || ' sick'
end Outcome
from translated_mytable
Please, try that query - it should do the trick - please just change t_tab into your_table_name and it should work
WITH
t_tab2 AS
(
SELECT t.code,
CASE WHEN SUBSTR(t.code,1,1) IN (1,2,3) THEN 8 END Out1,
CASE WHEN SUBSTR(t.code,2,1) IN (1,2,3) THEN 7 END Out2,
CASE WHEN SUBSTR(t.code,3,1) IN (1,2,3) THEN 6 END Out3,
CASE WHEN SUBSTR(t.code,4,1) IN (1,2,3) THEN 5 END Out4,
CASE WHEN SUBSTR(t.code,5,1) IN (1,2,3) THEN 4 END Out5,
CASE WHEN SUBSTR(t.code,6,1) IN (1,2,3) THEN 3 END Out6,
CASE WHEN SUBSTR(t.code,7,1) IN (1,2,3) THEN 2 END Out7,
CASE WHEN SUBSTR(t.code,8,1) IN (1,2,3) THEN 1 END Out8
FROM t_tab t
)
SELECT tt.code,
CASE WHEN tt.out1||tt.out2||tt.out3||tt.out4||
tt.out5||tt.out6||tt.out7||tt.out8 IS NULL THEN NULL
ELSE REGEXP_REPLACE(
REGEXP_REPLACE(RTRIM('Species' || ' ' || tt.out8 || ', ' || tt.out7|| ', '
|| tt.out6 || ', ' || tt.out5 || ', '
|| tt.out4 || ', ' || tt.out3 || ', '
|| tt.out2 || ', ' || tt.out1, ', ')
|| ' sick', ', | ,', ','), ',{1,}', ', ') END AS Outcome
FROM t_tab2 tt
It's giving me the result:
1 88881133 Species 1, 2, 3, 4 sick
2 88888888
3 88888833 Species 1, 2 sick
4 88888811 Species 1, 2 sick
5 88888111 Species 1, 2, 3 sick
6 88888881 Species 1 sick

Oracle 12c Concatenate with brackets where nulls are involved

We have a set of columns within a table we need to concatenate, and we need brackets around the third, fourth, fifth and sixth value, but also need nothing to appear if the column is null.
SELECT "ID",
NVL(PART || '.'|| SECTION ||'(' ||SUB1||')'|| '(' ||SUB2|| ')' || '('||SUB3||')' || '('||SUB4||')', '') as concatenated
FROM table1;
Places the values exactly right as long as there are values. When any one or more columns return null, we are getting an empty set of brackets for each null value.
Such as: 113.203()()()() when there are four null values
in this case we would need: 113.203
Or 113.450(h)(2)(iv)() when there is one null value.
here the desired results
would be 113.450(h)(2)(iv)
How can I change the script to leave out all the empty brackets when a null value is returned?
Thank you.
Hmmm, I think you want:
select id,
(part || '.' || section ||
(case when sub1 is not null then '(' || sub1 || ')' end) ||
(case when sub2 is not null then '(' || sub2 || ')' end) ||
(case when sub3 is not null then '(' || sub3 || ')' end) ||
(case when sub4 is not null then '(' || sub4 || ')' end)
) as concatenated
from table1;

Dynamically generate GRANT SQL from syscat.tabauth table

I have a database (on DB2 9.7) A in which suppose I have tables X,Y,Z...n
Now I have created same tables X,Y,Z...n in database B. I want to provide same GRANTs to users in database B as it was in database A. So based on SYSCAT.TABAUTH I am trying to generate GRANT SQLs. I have written the following query for it:
db2 "select 'GRANT '||
case INSERTAUTH
WHEN 'Y' THEN 'INSERT,'
WHEN 'N' THEN ' '
END||
case ALTERAUTH
WHEN 'Y' THEN 'ALTER,'
WHEN 'N' THEN ' '
END||
case DELETEAUTH
WHEN 'Y' THEN 'DELETE,'
WHEN 'N' THEN ' '
END||
case SELECTAUTH
WHEN 'Y' THEN 'SELECT,'
WHEN 'N' THEN ' '
END||
case UPDATEAUTH
WHEN 'Y' THEN 'UPDATE,'
WHEN 'N' THEN ' '
END||
' ON '||TABSCHEMA||'.'||TABNAME||' TO '||GRANTEE from SYSCAT.TABAUTH
where INSERTAUTH='Y' OR ALTERAUTH='Y' OR DELETEAUTH='Y' OR SELECTAUTH='Y' OR UPDATEAUTH='Y'"
However, the problem I am facing is of the additional ',' at end.
Suppose a user has only Insert auth, the above query will generate GRANT sql as:
GRANT INSERT, ON SCHEMA.TABLE TO GRANTEENAME
or if user has insert and select grants then:
GRANT INSERT,SELECT, ON SCHEMA.TABLE TO GRANTEENAME
How can I solve this? Please help..
This is what I finally made and it works fine:
db2 "SELECT
'GRANT ' ||
SUBSTR(T.AUTHSTRING, 1 ,LENGTH(T.AUTHSTRING) - 1)
|| T.TABNAME
FROM(
select
case INSERTAUTH
WHEN 'Y' THEN 'INSERT,'
WHEN 'N' THEN ''
END
||
case ALTERAUTH
WHEN 'Y' THEN 'ALTER,'
WHEN 'N' THEN ''
END
||
case DELETEAUTH
WHEN 'Y' THEN 'DELETE,'
WHEN 'N' THEN ''
END
||
case SELECTAUTH
WHEN 'Y' THEN 'SELECT,'
WHEN 'N' THEN ''
END
||
case UPDATEAUTH
WHEN 'Y' THEN 'UPDATE,'
WHEN 'N' THEN ''
END
AS AUTHSTRING,
' ON ' ||TRIM(TABSCHEMA)||'.'||TRIM(TABNAME)||' TO ' ||GRANTEE AS TABNAME
from SYSCAT.TABAUTH
where INSERTAUTH='Y'
OR ALTERAUTH='Y'
OR DELETEAUTH='Y'
OR SELECTAUTH='Y'
OR UPDATEAUTH='Y'
) AS T"
You can always push the dynamic part into a sub-query, and then use a combination of LENGTH() and SUBSTR() to trim off the extra comma. Here is your SQL I modified a bit:
SELECT
'GRANT' ||
SUBSTR(T.AUTHSTRING, 1 LENGTH(T.AUTHSTRING) -1)
|| T.TABNAME
FROM(
select
case INSERTAUTH
WHEN 'Y' THEN 'INSERT,'
WHEN 'N' THEN ' '
END
||
case ALTERAUTH
WHEN 'Y' THEN 'ALTER,'
WHEN 'N' THEN ' '
END
||
case DELETEAUTH
WHEN 'Y' THEN 'DELETE,'
WHEN 'N' THEN ' '
END
||
case SELECTAUTH
WHEN 'Y' THEN 'SELECT,'
WHEN 'N' THEN ' '
END
||
case UPDATEAUTH
WHEN 'Y' THEN 'UPDATE,'
WHEN 'N' THEN ' '
END
AS AUTHSTRING,
' ON ' || RTRIM(TABSCHEMA) || '.' || RTRIM(TABNAME)||' TO ' || RTRIM(GRANTEE) AS TABNAME
from SYSCAT.TABAUTH
where INSERTAUTH='Y'
OR ALTERAUTH='Y'
OR DELETEAUTH='Y'
OR SELECTAUTH='Y'
OR UPDATEAUTH='Y'
) AS T
I tested this, and it worked on LUW 9.7 and z/OS 9.1.