Merge columns with empty values in oracle - sql

I have two columns of data name1 and name2. I need to merge these columns but they are arranged like this:
name1 | name2
1 empty
empty 2
3 empty
empty 4
Here empty means a blank space in the table.
I need the output to be like this
1
2
3
4

This can be achieved with a simple NVL
WITH
sample_data (name1, name2)
AS
(SELECT 1, NULL FROM DUAL
UNION ALL
SELECT NULL, 2 FROM DUAL
UNION ALL
SELECT 3, NULL FROM DUAL
UNION ALL
SELECT NULL, 4 FROM DUAL)
SELECT nvl(name1, name2) as names
FROM sample_data;

Related

Oracle SQL: Combine list of char with values

In Oracle SQL, I want to create a view.
In Column 1, it should have a distinct list of chars.
select distinct *name* from view1
--> name1
name2
name3
name4...
Now in the second column, there should be numbers, which depend on this number:
select max(number) number_max from view2
--> 17
Now I want the second column to be ascending, depending on that number. The list of numbers for each name. The table should look like:
name1 18 ->(number_max+1)
name1 19 ->(number_max+2)
name1 20
name2 18
name2 19
name2 20
name3 18
....
How do I do this? Thank you so much!
This is how I understood it:
Sample data (your views, view1 and view2, simplified):
SQL> with
2 view1 (name) as
3 (select 'name1' from dual union all
4 select 'name1' from dual union all
5 select 'name1' from dual union all
6 select 'name2' from dual union all
7 select 'name3' from dual union all
8 select 'name3' from dual
9 ),
10 view2 (c_number) as
11 (select 15 from dual union all
12 select 17 from dual
13 )
14 --
Query begins here; subquery that is cross-joined to view1 just fetches the maximum number column value which is then added to result of the row_number analytic function that partitions data per each name:
15 select
16 a.name as col1,
17 row_number() over (partition by a.name order by null) + b.number_max as col2
18 from view1 a cross join (select max(c_number) number_max from view2) b
19 order by 1, 2;
COL1 COL2
----- ----------
name1 18
name1 19
name1 20
name2 18
name3 18
name3 19
6 rows selected.
SQL>
You can use GROUP BY name to find the DISTINCT names and find the maximum maximum by nesting an MAX aggregation function inside a MAX analytic function and then CROSS JOIN to a row-generator.
For example, if you wanted 3 rows for each name:
SELECT m.name,
m.number_max + l.value AS value
FROM ( SELECT name,
MAX(MAX("NUMBER")) OVER () AS number_max
FROM table_name
GROUP BY name
) m
CROSS JOIN (
SELECT LEVEL AS value FROM DUAL CONNECT BY LEVEL <= 3
) l;
Which, if you have the sample data:
CREATE TABLE table_name (name, "NUMBER") AS
SELECT 'name1', 17 FROM DUAL UNION ALL
SELECT 'name1', 1 FROM DUAL UNION ALL
SELECT 'name1', 7 FROM DUAL UNION ALL
SELECT 'name2', 15 FROM DUAL UNION ALL
SELECT 'name2', 15 FROM DUAL UNION ALL
SELECT 'name3', 5 FROM DUAL UNION ALL
SELECT 'name3', 7 FROM DUAL UNION ALL
SELECT 'name4', 2 FROM DUAL UNION ALL
SELECT 'name4', 1 FROM DUAL;
Outputs:
NAME
VALUE
name1
18
name2
18
name3
18
name4
18
name1
19
name2
19
name3
19
name4
19
name1
20
name2
20
name3
20
name4
20
db<>fiddle here

How do I extract the first 3 consonates from a string field SQL?

how can I extract from a field in records that contain names only the first 3 consonants and if a name does not have 3 consonants it adds the first vowel of the name?
For example, if I had the following record in the People table:
Field:Name
VALUE:Richard result=> RCH
FIELD:Name
VALUE:Paul result=> PLA
Here's one option; read comments within code.
Sample data:
SQL> with test (name) as
2 (select 'Richard' from dual union all
3 select 'Paul' from dual
4 ),
Query begins here:
5 temp as
6 -- val1 - consonants; val2 - vowels
7 (select
8 name,
9 translate(upper(name), '#AEIOU', '#') val1,
10 translate(upper(name), '#BCDFGHJKLMNPQRSTWXYZ', '#') val2
11 from test
12 )
13 -- finally: if there are enough consonants (val1's length is >= 3), return the first 3
14 -- letters (that's WHEN).
15 -- Otherwise, add as many vowels as necessary (that's what ELSE does)
16 select name,
17 case when length(val1) >= 3 then substr(val1, 1, 3)
18 else val1 || substr(val2, 1, 3 - length(val1))
19 end result
20 from temp;
NAME RESULT
------- --------------
Richard RCH
Paul PLA
SQL>
Just for fun using regexp:
select
name
,substr(
regexp_replace(
upper(name)
,'^([AEIOU]*)([^AEIOU]*)([AEIOU]*)([^AEIOU]*)([AEIOU]*)([^AEIOU]*).*'
,'\2\4\6\1\3\5'
),1,3) as result
from test;
([AEIOU]*) - is a group of vowels, 0 or more characters
([^AEIOU]*) - is a group of not-vowels (or consonants in this case), 0 or more characters
so this regexp looks for a pattern (vowels1)(consonants1)(vowels2)(consonants2)(vowels3)(consonants3) and reorders it to (consonants1)(consonants2)(consonants3)(vowels1)(vowels2)(vowels3)
then we just take first 3 characters from the reordered string
Full test case:
with test (name) as
(select 'Richard' from dual union all
select 'Paul' from dual union all
select 'Annete' from dual union all
select 'Anny' from dual union all
select 'Aiua' from dual union all
select 'Isaiah' from dual union all
select 'Sue' from dual
)
select
name
,substr(
regexp_replace(
upper(name)
,'^([AEIOU]*)([^AEIOU]*)([AEIOU]*)([^AEIOU]*)([AEIOU]*)([^AEIOU]*).*'
,'\2\4\6\1\3\5'
),1,3) as result
from test;
NAME RESULT
------- ------------
Richard RCH
Paul PLA
Annete NNT
Anny NNY
Aiua AIU
Isaiah SHI
Sue SUE
7 rows selected.

Count distinct values separated by a comma

I have this table called test
id
my_list
1
aa//11, aa//34, ab//65
2
bb//43, bb//43, be//54
3
4
cc//76
I want to count the distinct values in my_list, where each item in the list is separated by a comma. In this case:
id=1 will have 3 distinct values
id=2 will have 2 distinct values as bb//43 as shown up twice, thus 2 distinct values
id=3 will have 0 distinct values as it as an empty list
id=4 will have 1 since there is only 1 item in the list
I want to do this in pure SQL and not using a custom made procedure. I tried with the statement below but it is showing 1.
SELECT id, COUNT(DISTINCT my_list) as my_count
FROM test;
Expected result:
id
my_count
1
3
2
2
3
0
4
1
You need to turn your list into table to count distinct inside it. With json_table, for example.
with a(id, my_list) as (
select 1, 'aa//11, aa//34, ab//65' from dual union all
select 2, 'bb//43, bb//43, be//54' from dual union all
select 3, null from dual union all
select 4, 'cc//76' from dual
)
select
id
, (
select count(distinct val)
from json_table(
/*Replace comma with quotes and comma: ','
And wrap with array brackets
*/
'[''' || regexp_replace(my_list, '\s*,\s*', ''',''') || ''']'
, '$[*]'
columns ( val varchar(20) path '$')
)
) as cnt
from a
ID | CNT
-: | --:
1 | 3
2 | 2
3 | 0
4 | 1
db<>fiddle here

Removing first 'G' character of entire column values in table if it is starting from 'G'

I wanted to remove first 'G' character of full column values of table only if it exist.
I have tried the substr function to remove first char but it will remove the first char even if it is not 'G'. I only wanted to remove first char of entire column values if it is 'G'.
For example in myTable the column values are as follows:
G12345
332157
G54337
G54332
534535
Expected result is as follows:
12345
332157
54337
54332
534535
Wanted to write update query to update the entire column value.
Based on your description, you can use regexp_replace():
select regexp_replace('G12345', 'G', '', 1, 1)
If you only want to remove a 'G' at the beginning of the string, you can use '^G' for the pattern.
Based on your data, you can just use replace():
select replace('G12345', 'G', '')
This removes all 'G's. But your data only seems to have one.
For an update you would just include the logic as an update:
update t
set col = replace(col, 'G', '')
where col like '%G%';
Or whichever of the above functions is what you really want to do.
You want to update the rows where the value starts with a 'G', so use a WHERE clause:
update mytable
set value = substr(value, 2)
where value like 'G%';
As you want to replace only the first G, then
SQL> with test (col) as
2 (select 'G12345' from dual union all
3 select '332157' from dual union all
4 select '11G222' from dual
5 )
6 select col,
7 substr(col, case when substr(col, 1, 1) = 'G' then 2 else 1 end) result
8 from test;
COL RESULT
------ ------
G12345 12345
332157 332157
11G222 11G222
SQL>
You can use:
SELECT CASE WHEN value LIKE 'G%' THEN SUBSTR( value, 2 ) ELSE value END
AS value_without_g
FROM myTable
Which, from the sample data:
CREATE TABLE myTable ( value ) AS
SELECT 'G12345' FROM DUAL UNION ALL
SELECT '332157' FROM DUAL UNION ALL
SELECT 'G54337' FROM DUAL UNION ALL
SELECT 'G54332' FROM DUAL UNION ALL
SELECT '534535' FROM DUAL;
Outputs:
| VALUE_WITHOUT_G |
| :-------------- |
| 12345 |
| 332157 |
| 54337 |
| 54332 |
| 534535 |
db<>fiddle here

Selecting rows where column having number as substring

I have to write a query to fetch all the rows with a column containing numbers as substring
Data
------
abc123
defgh
wz127bdn
Now my desired result is
Result
-----
abc123
wz127bdn
I wrote the query like
SELECT data
FROM table
WHERE data like '%[0-9]%'
But this is not fetching the result.
You need a REGEXP_LIKE:
SQL> with test(data) as (
2 select 'abc123' from dual union all
3 select 'defgh' from dual union all
4 select 'wz127bdn' from dual union all
5 select '[0-9]' from dual
6 )
7 select *
8 from test
9 where regexp_like(data, '[0-9]')
10 ;
DATA
--------
abc123
wz127bdn
[0-9]
LIKE will not interpret '[0-9]' as "look for a digit", but exactly as you write it, thus searching for the string '[0-9]':
SQL> with test(data) as (
2 select 'abc123' from dual union all
3 select 'defgh' from dual union all
4 select 'wz127bdn' from dual union all
5 select '[0-9]' from dual
6 )
7 select *
8 from test
9 where data like '%[0-9]%' ;
DATA
--------
[0-9]
Use regexp_like() in Oracle:
SELECT data
FROM table
WHERE regexp_like(data, '[0-9]');
Note that the wildcards are not necessary, because regular expressions match anywhere in the string. If you like, you can do:
WHERE regexp_like(data, '.*[0-9].*');