Oracle : Select only particular value from a row - sql

I have a like below
data :
1234=A||1456=B||1789=C
1245=||1234=V
1234,1133
1456=||1234=1,234||1234
so i wanted to remove all the value after = and before | except for 1234.
expected data :
1234=A||1456=||1789=
1245=||1234=V
1234,1133
1456=||1234=1,234||1234

You can use:
SELECT REGEXP_REPLACE(
value,
'(^|\|)((1234=.*?)|(\d+=).*?)(\||$)',
'\1\3\4\5'
) AS value
FROM table_name
Which, for the sample data:
CREATE TABLE table_name ( value ) AS
SELECT '1234=A||1456=B||1789=C' FROM DUAL UNION ALL
SELECT '1245=||1234=V' FROM DUAL UNION ALL
SELECT '1234,1133' FROM DUAL UNION ALL
SELECT '1456=||1234=1,234||1234' FROM DUAL;
Outputs:
VALUE
1234=A||1456=||1789=
1245=||1234=V
1234,1133
1456=||1234=1,234||1234
sqlfiddle here

Related

Check if all characters are 'X'

I have the below table:
COL
---
XXY
YXX
XXX
NULL
I want to filter out the rows which don't consist of all 'X's.
Expected output:
COL
---
XXX
We can use REGEXP_LIKE here:
SELECT COL
FROM yourTable
WHERE REGEXP_LIKE(COL, '^X+$'); -- ^X+$ means all X from start to end
Another similar version:
SELECT COL
FROM yourTable
WHERE NOT REGEXP_LIKE(COL, '[^X]'); -- this means no non X present
Another option(without using a regular expression) might be using
WITH t(col) AS
(
SELECT 'XXY' FROM dual UNION ALL
SELECT 'YXX' FROM dual UNION ALL
SELECT 'XXX' FROM dual UNION ALL
SELECT NULL FROM dual UNION ALL
SELECT 'XX ' FROM dual
)
SELECT *
FROM t
WHERE REPLACE(NVL(col,'Y'),'X') IS NULL;
COL
----
XXX
without forgetting the case col = NULL through use of a NVL()
You can use the following syntax (assuming you are using MySQL database 5.6 or greater version):
SELECT * FROM table_name WHERE col_name REGEXP '^X+$';
If you don't want/have regexp then:
WITH
tbl AS
( Select 'XXY' "COL" From dual Union All
Select 'YXX' "COL" From dual Union All
Select 'XXX' "COL" From dual Union All
Select null "COL" From dual
)
Select COL
From tbl
Where Length(Nvl(COL, 'Z')) - Length( Replace( Upper(Nvl(COL, 'Z')), 'X', '')) Is Null
COL
---
XXX
This covers both small 'x' and capital 'X' if needed and returns original COL value

Returning result in Json and table type SQL Oracle

I have a table in which with repeating id.
The goal is (to make a select) to get all the results of the repeating id to pour against each id in Json format as id it's not in Json
id,yyyy,name
1,2010,a
1,2011,b
2,2010,a
3,2010,c
3,2011,a
4,2011,v
Desired result
id, column(json)
1 {"2010":"a","2011","b"}
2 {"2010":"a","2010":"c"}
3 {"2010":"c","2011":"a"}
4 {"2011":"v"}
with data(id, y, name) as (
select 1,2010,'a' from dual union all
select 1,2011,'b' from dual union all
select 2,2010,'a' from dual union all
select 3,2010,'c' from dual union all
select 3,2011,'a' from dual union all
select 4,2011,'v' from dual -- union all
)
select id, json_objectagg(
key to_char(y) value name) as obj
from data
group by id
;
1 {"2010":"a","2011":"b"}
2 {"2010":"a"}
3 {"2010":"c","2011":"a"}
4 {"2011":"v"}

Find value that is not a number or a predefined string

I have to test a column of a sql table for invalid values and for NULL.
Valid values are: Any number and the string 'n.v.' (with and without the dots and in every possible combination as listed in my sql command)
So far, I've tried this:
select count(*)
from table1
where column1 is null
or not REGEXP_LIKE(column1, '^[0-9,nv,Nv,nV,NV,n.v,N.v,n.V,N.V]+$');
The regular expression also matches the single character values 'n','N','v','V' (with and without a following dot). This shouldn't be the case, because I only want the exact character combinations as written in the sql command to be matched. I guess the problem has to do with using REGEXP_LIKE. Any ideas?
I guess this regexp will work:
NOT REGEXP_LIKE(column1, '^([0-9]+|n\.?v\.?)$', 'i')
Note that , is not a separator, . means any character, \. means the dot character itself and 'i' flag could be used to ignore case instead of hard coding all combinations of upper and lower case characters.
No need to use regexp (performance will increase by large data) - plain old TRANSLATE is good enough for your validation.
Note that the first translate(column1,'x0123456789','x') remove all numeric charcters from the string, so if you end with nullthe string is OK.
The second translate(lower(column1),'x.','x') removes all dots from the lowered string so you expect the result nv.
To avoid cases as n.....v.... you also limit the string length.
select
column1,
case when
translate(column1,'x0123456789','x') is null or /* numeric string */
translate(lower(column1),'x.','x') = 'nv' and length(column1) <= 4 then 'OK'
end as status
from table1
COLUMN1 STATUS
--------- ------
1010101 OK
1012828n
1012828nv
n.....v....
n.V OK
Test data
create table table1 as
select '1010101' column1 from dual union all -- OK numbers
select '1012828n' from dual union all -- invalid
select '1012828nv' from dual union all -- invalid
select 'n.....v....' from dual union all -- invalid
select 'n.V' from dual; -- OK nv
You can use:
select count(*)
from table1
WHERE TRANSLATE(column1, ' 0123456789', ' ') IS NULL
OR LOWER(column1) IN ('nv', 'n.v', 'nv.', 'n.v.');
Which, for the sample data:
CREATE TABLE table1 (column1) AS
SELECT '12345' FROM DUAL UNION ALL
SELECT 'nv' FROM DUAL UNION ALL
SELECT 'NV' FROM DUAL UNION ALL
SELECT 'nV' FROM DUAL UNION ALL
SELECT 'n.V.' FROM DUAL UNION ALL
SELECT '...................n.V.....................' FROM DUAL UNION ALL
SELECT '..nV' FROM DUAL UNION ALL
SELECT 'n..V' FROM DUAL UNION ALL
SELECT 'nV..' FROM DUAL UNION ALL
SELECT 'xyz' FROM DUAL UNION ALL
SELECT '123nv' FROM DUAL;
Outputs:
COUNT(*)
5
or, if you want any quantity of . then:
select count(*)
from table1
WHERE TRANSLATE(column1, ' 0123456789', ' ') IS NULL
OR REPLACE(LOWER(column1), '.') = 'nv';
Which outputs:
COUNT(*)
9
db<>fiddle here

Oracle SQL find missing sequence in varchar2 field

I am new to oracle and to this forum. I have searched and found answers on how to do this with a column of just numbers but this has txt at the beginning then a sequenced number.
I have a table that has a varchar2 column named myid which has characters with a number at the end which is in order the number at the end is always 6 digits with leading zeros.
Hello_002190
Hello_002188
Bye_000187
Bye_000185
Bye_000184
Get_008133
Get_008131
Gone_001112
Gone_001110
Gone_001109
I need an Oracle SQL script that will show me all the missing rows.
The result for the above should be:
Hello_002189
Bye_000186
Get_008132
Gone_001111
Thanks in advance for the help
SQL Fiddle
Oracle 11g R2 Schema Setup:
CREATE TABLE table_name ( value ) AS
SELECT 'Hello_002190' FROM DUAL UNION ALL
SELECT 'Hello_002188' FROM DUAL UNION ALL
SELECT 'Bye_000187' FROM DUAL UNION ALL
SELECT 'Bye_000185' FROM DUAL UNION ALL
SELECT 'Bye_000184' FROM DUAL UNION ALL
SELECT 'Get_008133' FROM DUAL UNION ALL
SELECT 'Get_008131' FROM DUAL UNION ALL
SELECT 'Gone_001112' FROM DUAL UNION ALL
SELECT 'Gone_001110' FROM DUAL UNION ALL
SELECT 'Gone_001109' FROM DUAL;
Query 1:
WITH data ( prefix, suffix ) AS (
SELECT SUBSTR( value, 1, INSTR( value, '_' ) ),
TO_NUMBER( SUBSTR( value, INSTR( value, '_' ) + 1 ) )
FROM table_name
),
bounds ( prefix, min_suffix, max_suffix ) AS (
SELECT prefix, MIN( suffix ), MAX( suffix )
FROM data
GROUP BY prefix
)
SELECT prefix || TO_CHAR( column_value, 'FM000000' ) AS missing_value
FROM bounds b
CROSS JOIN
TABLE(
CAST(
MULTISET(
SELECT b.min_suffix + LEVEL - 1
FROM DUAL
CONNECT BY b.min_suffix + LEVEL - 1 <= b.max_suffix
) AS SYS.ODCINUMBERLIST
)
)
MINUS
SELECT value FROM table_name
Results:
| MISSING_VALUE |
|---------------|
| Bye_000186 |
| Get_008132 |
| Gone_001111 |
| Hello_002189 |

How to convert String in SQL (ORACLE)

I try to select from table_1 where ITEM_FIELD_A is not in ITEM_FIELD_B. The Item_FIELD_B value are look as below. I was expecting no COVER_TAPE & SHIPPING_REELS will be selected. But unfortunately, it's not working.
The sql I used to select the table
select * from table_1 where MST.ITEM_FIELD_A not in ITEM_FIELD_B
Question:
In Oracle, is there any function to decode the string. so that the above select statement will not return COVER_TAPE and SHIPPING_REELS??
The IN operator would be used when you wish to compare (or negate) one item in a list such as
WHERE ITEM_FIELD_A NOT IN ('COVER_TAPE', 'SHIPPING_REELS', '')
What you want is the LIKE operator:
WHERE ITEM_FIELD_B NOT LIKE '%' || ITEM_FIELD_A || '%'
Apologies if I got the wildcard wrong, been a while since I last touched Oracle.
Check out below Query:
WITH TAB1 AS
( SELECT 'COVER_TAPE' ITEM_A FROM DUAL
UNION
SELECT 'CARRIER_TAPE' ITEM_A FROM DUAL
UNION
SELECT 'SHIPPING_REELS' ITEM_A FROM DUAL
),
TAB2 AS
(
SELECT 'COVER_TAPE,SHIPPING_REELS' ITEM_B FROM DUAL
)
SELECT ITEM_A, ITEM_B FROM TAB1, TAB2 WHERE INSTR(ITEM_B, ITEM_A) <=0
INSTR will return >0 if same sequence of characters is available.
SQL> with t(x , y) as
2 (
3 select 'A', q'[('A','B','C')]' from dual union all
4 select 'R', q'[('A','B','C','D')]' from dual union all
5 select 'C', q'[('A', 'C','D')]' from dual
6 )
7 select x, y
8 from t where y not like q'[%']'||x||q'['%]'
9 /
X Y
---------- --------------------------------------------------
R ('A','B','C','D')