using decode with input as comma separated list - sql

This could be simple question for experts.
Here is my requirement. I have to use DECODE and match the string containing comma separated values.
Here is sample SQL: 'A' is column value from table, 'A,B'C' is comma separated string passed as expression to sql
SELECT DECODE('A' , 'A,B,C', 'true', 'false') FROM DUAL;
The above SQL should return true as csv expression contains 'A'.
Please help me writing this SQL

If I understand your question, you are trying to determine if a string is within another string?
select case when instr( 'A,B,C', 'A' ) > 0
then 'True'
else 'False'
end
from dual
Add the DECODE version
select decode( instr( 'A,B,C', 'A' ), 0, 'False', 'True' )
from dual

First, don't use decode(). Use the ANSI standard CASE statement. The answer to your question is that you can use LIKE:
SELECT (CASE WHEN ',' || 'A,B,C' || ',' LIKE '%,' || 'A' || ',%'
THEN 'true' ELSE 'false'
END)
FROM DUAL;
Note: The string concatenation is just because I suspect the values are variables. The simpler form is:
SELECT (CASE WHEN ',A,B,C,' LIKE '%,A,%'
THEN 'true' ELSE 'false'
END)
FROM DUAL;

Using DECODE, you can do it like this:
SELECT DECODE(INSTR('A,B,C', 'A'), 0, 'false', 'true') FROM DUAL;
where
INSTR('Comma separated string', 'column value to match') will return 0 if the column value is not in the comma separated string. In your example,
INSTR('A,B,C', 'A') will return a value greater than 0 and INSTR('D,B,C', 'A') will return 0. So then DECODE can check if the return value of INSTR() is 0 then return false otherwise return true.

Related

How to find values that contains only 0's and any other digit for example 000000001 or 0000010001 or 010101 or 0002 or 02020 or 0090 etc.?

I want to find 'default type values' in SQL that is entered when something like an ID number of company registration number is entered. Some of the values I see is a combination of 0's and another digit from 1-9. Examples I have seen is 00000001, 0000100, 000000002, 000001111, 0000090009, etc. The values vary in length also. Is there a way to find these values without hard coding? The value should contain at least one 0 and one or more of any other digit.
You want all strings that consist of only zero and one other digit. I.e. you want to find '0101', but not '0102'.
In order to do this, remove all zeros first. From the remaining string remove all digits equaling to its first character. This will result in an empty string or a string consisting of additional digits or characters. Only select those resulting in an empty string.
select *
from mytable
where replace(replace(value, '0', ''), substring(replace(value, '0', ''), 1, 1), '') = '';
Demo: https://dbfiddle.uk/?rdbms=sqlserver_2019&fiddle=c307bbbf21ceeae619a966e995c3a567
You can use ISNUMERIC() function
SELECT ISNUMERIC(0000004);
This will return 1
SELECT ISNUMERIC('A');
This will return 0
So if you want to select all columns that are numeric only you can use this logic:
select *
from test
where ISNUMERIC(colA) = 1
Here is a small demo
Or you can use TRY_CAST() function:
select *
from test
where try_cast(colA as int) is not null
Alternative solution:
SELECT value
FROM mytable
CROSS JOIN (
SELECT '1' AS num
UNION ALL
SELECT '2'
UNION ALL
SELECT '3'
UNION ALL
SELECT '4'
UNION ALL
SELECT '5'
UNION ALL
SELECT '6'
UNION ALL
SELECT '7'
UNION ALL
SELECT '8'
UNION ALL
SELECT '9'
) n
WHERE REPLACE(REPLACE(value, '0', ''), num, '') = ''
AND REPLACE(value, '0', '') <> ''
AND value LIKE '%0%'

Replace Function for specific values

I have a table like this:
Article
Date
Status
Code
In the column "Status" are values like '00', '01', 'OB'
In the column "Code" are values like:
[05]+000569
[1B] 5555
690KB
-859
I am just interested for rows where "Status" = '00'.
The status '00' shows just values like [05]+000569.
These values should be trimmed with the following function:
select replace(regexp_substr(Code, '(^|[+])[0-9]+'), '+', '')
How can I build a SELECT SQL with this function just for rows where "Status" = '00' ?
I see. You want a case expression:
select (case when status = '00' then replace(regexp_substr(Code, '(^|[+])[0-9]+'), '+', '')
end)
"Trim" for status = '00', don't for other statuses:
SELECT CASE
WHEN status = '00' --> trim
THEN --> for
REPLACE (REGEXP_SUBSTR (Code, '(^|[+])[0-9]+'), '+', '') --> '00'
ELSE
code --> else, do nothing
END
AS code
FROM your_table

Select Statement that returns a result where the text characters contains only 0s or only 9s but length doesn't matter

I'm trying to write a select statement that returns column A when column B contains '0' or '9' or '00' or '99' or '000' or '999' and so forth. The values are TEXT. Any help is appreciated!
You could use:
SELECT colA
FROM tab
WHERE REPLACE(colB, '9', '') = ''
OR REPLACE(colB, '0', '') = '';
DBFiddle Demo
SELECT *
FROM tab
WHERE col like '%9%' or col like '%0%'

How to use subquery inside DECODE in Oracle

I am trying to use a sub-query inside and Oracle Decode statement as shown below
RPAD(NVL(DECODE(TRIM(ST.StudentCode),'AB','CA','TM','CH',(Select InternalNumber from Address where State = SA.STATECODE) <=2,'PAS', ST.StudentCode), ' '), 3, ' ')
when I am running this part with my original query I am getting error as "Missing right paranthesis" in the same line. What is being wrong here?
Just use a single case expression:
RPAD( (CASE WHEN TRIM(ST.StudentCode) = 'AB' THEN 'CA',
WHEN TRIM(ST.StudentCode) = 'TM' THEN 'CH',
WHEN (Select a.InternalNumber from Address a where a.State = SA.STATECODE) <= 2 THEN 'PAS'
ELSE COALESCE(ST.StudentCode, ' '),
), 3, ' ')
You can add case expression inside your sub query:
RPAD(NVL(DECODE(TRIM(ST.StudentCode),'AB','CA','TM','CH',CASE WHEN (Select InternalNumber from Address where State = SA.STATECODE) <=2 THEN 'PAS' ELSE ST.StudentCode END), ' '), 3, ' ')
Oracle Database searches for the first WHEN ... THEN pair for which expr is equal to comparison_expr and returns return_expr. If none of the WHEN ... THEN pairs meet this condition, and an ELSE clause exists, then Oracle returns else_expr. Otherwise, Oracle returns null.

remove extra + from text SQL

this refers to a question asked by someone else previously
previous question
my question is how do I adapt this solution so that before any function/script is ran the name and value fields are stripped of any additional + and updated so no additional + remain.
For e.g.
Name Value
A+B+C+ 1+2+3+
A++B 1++2
this should be updated to
Name Value
A+B+C 1+2+3
A+B 1+2
once this update has taken place, I can run the solution provided in the previous question.
Thanks
You need to replace ++ with + and to remove the + at the end of the string.
/* sample data */
with input(Name, Value) as (
select 'A+B+C+' ,'1+2+3+' from dual union all
select 'A++B' ,'1++2' from dual
)
/* query */
select trim('+' from regexp_replace(name, '\+{2,}', '+') ) as name,
trim('+' from regexp_replace(value, '\+{2,}', '+') ) as value
from input
If you need to update a table, you may need:
update yourTable
set name = trim('+' from regexp_replace(name, '\+{2,}', '+') ),
value= trim('+' from regexp_replace(value, '\+{2,}', '+') )
In a more compact way, without the external trim ( assuming you have no leading +):
/* sample data */
with input(Name, Value) as (
select 'A+B+C+' ,'1+2+3+' from dual union all
select 'A++B+++C+' ,'1++2+++3+' from dual union all
select 'A+B' ,'1+2' from dual
)
/* query */
select regexp_replace(name, '(\+)+(\+|$)', '\2') as name,
regexp_replace(value, '(\+)+(\+|$)', '\2') as value
from input
You could use something on the lines of:
Select substr('1+2+3+', 0, length('1+2+3+')-1) from dual ;
Select replace('1++2', '++', '+') from dual;
I'm assuming you have the output already present in a variable you can play with.
EDIT:
Here's a function that can solve the problem (You can call this function in your select clauses thereby solving the problem):
CREATE OR REPLACE Function ReplaceChars
( name_in IN varchar2 )
RETURN varchar2
IS
changed_string varchar2(20) ;
BEGIN
changed_string:=replace(name_in, '++', '+') ;
CASE WHEN substr(changed_string, -1) in ('+')
then
changed_string:=substr(changed_string,0, length(changed_string) - 1) ;
else changed_string:=changed_string ;
end CASE ;
RETURN changed_string;
END;
You can use the below:
LTRIM(RTRIM (REGEXP_REPLACE (column_name, '\+{2,}', '+'), '+'),'+')
Eg:
SELECT LTRIM(RTRIM (REGEXP_REPLACE ('+A+++B+C+++D++', '\+{2,}', '+'), '+'),'+') VALUE
FROM DUAL;
returns output: A+B+C+D
if youre working with ssms, GIVE IT A GO:::
UPDATE tablename
SET colname=
CASE colname WHEN LIKE '%++%' THEN
WHILE colname LIKE '%++%'
(REPLACE(colname,++,+))
END LOOP
WHEN LIKE '%+' THEN
SUBSTR(colname, 1, LENGTH(colname)-1)
WHEN LIKE '+%' THEN
SUBSTR(colname, 2, LENGTH(colname))
ELSE
colname
END