How to update a value within a column with another value- Oracle - sql

I have a static table that I want to replace a particular value with a string. In other words, in my table, I want to replace the value dog in the type_1 column with 'primate'.
Here is my table:
t_id|type_1|count
1, dog, 22
2, cat, 55
3, bird, 12
Here is my expected output:
t_id|type_1|count
1, primate, 22
2, cat, 55
3, bird, 12
As you can see, I just want to replace the value dog with the value primate.
Here is my code so far:
SELECT REPLACE(t.type_1, 'dog', 'primate')
FROM table_1 t
where t.type_1 = 'dog' and t.t_id='1'
I am new to oracle sql so the syntax is a bit confusing to me. Any ideas or suggestions would help.

If you just want a query, use a case expression:
select t.t_id,
(case when t.type_1 = 'dog' then 'primate' else t.type_1 end) as type_1,
t.count
from table_1 t;
If you want to change the value in the table (i.e. permanently), use update:
update table_1
set type_1 = 'primate'
where type_1 = 'dog';

Looks like update.
This is what you have:
SQL> select * from animal;
T_ID TYPE_1 CNT
---------- ---------- ----------
1 dog 22
2 cat 55
3 bird 12
Change "dog" to "primate":
SQL> update animal set type_1 = 'primate' where type_1 = 'dog';
1 row updated.
Result:
SQL> select * from animal;
T_ID TYPE_1 CNT
---------- ---------- ----------
1 primate 22
2 cat 55
3 bird 12
SQL>
Or, if you just need a select statement, then case might do:
SQL> select t_id,
2 case when type_1 = 'dog' then 'primate'
3 else type_1
4 end as type,
5 cnt
6 from animal;
T_ID TYPE CNT
---------- ---------- ----------
1 primate 22
2 cat 55
3 bird 12
SQL>

Related

I have this small table having duplicate id and names and I want to replace null values with names using there ID

I got it with self join:
select a.id, a.name, b.id, b.name, nvl(a.name,b.name)
from names a
join names b
on a.id = b.id
where a.name is null and b.name is not null;
But don't no how do I update it in the table.
I tried update statement but did not work
[]
Problem is that there are no unique [id, name] combinations in rows that don't have empty name columns.
SQL> select * From test;
ID NAME
---------- ------
1 naya
1 naya
2 amar
3 dhruv --> here
4 shyla
4 shyla
3 diya --> here
5 ananya
6 ishaan
5
2
2
1
3
14 rows selected.
SQL>
So, which name would you want to get for ID = 3? You can't have both, so - one option is to select any, e.g. max.
SQL> update test a set
2 a.name = (select max(b.name)
3 from test b
4 where b.id = a.id
5 )
6 where a.name is null;
5 rows updated.
Result:
SQL> select * From test;
ID NAME
---------- ------
1 naya
1 naya
2 amar
3 dhruv
4 shyla
4 shyla
3 diya
5 ananya
6 ishaan
5 ananya
2 amar
2 amar
1 naya
3 diya
14 rows selected.
SQL>
From Oracle 12, you can use:
UPDATE names n
SET name = (SELECT name
FROM names x
WHERE x.id = n.id
ORDER BY name NULLS LAST
FETCH FIRST ROW ONLY)
WHERE name IS NULL
db<>fiddle here

Oracle SQL: Select with variable and condition

I'm creating a query with a condition depending on the result of a variable.
If PROD = 'alpha' I need to show only models 2,3,4,5 and 6;
if PROD = 'beta' that only models 0 and 1 appear.
DEFINE PROD = 'ALPHA'
SELECT CAR_CODE, CAR, MODELS
FROM TB_CAR_MODELS
WHERE (
CASE PROD
WHEN 'ALPHA' THEN MODELS IN (2,3,4,5,6)
WHEN 'BETA' THEN MODELS IN (0,1)
END
);
I created this query but it's not working. Returns the error:
00000 - "missing keyword"
Can you help me please? Thanks
A few sample rows:
SQL> select * from tb_car_models;
CAR_CODE CAR MODELS
---------- ---- ----------
1 BMW 2 -- ALPHA
2 Audi 5 -- ALPHA
3 Opel 0 -- BETA
SQL>
As I'm running it in SQL*Plus, I'm using a substitution variable:
SQL> select *
2 from tb_car_models
3 where models in (select models
4 from tb_car_models
5 where models in (2, 3, 4, 5, 6)
6 and '&&prod' = 'ALPHA'
7 union all
8 select models
9 from tb_car_models
10 where models in (0, 1)
11 and '&&prod' = 'BETA'
12 );
Enter value for prod: ALPHA
CAR_CODE CAR MODELS
---------- ---- ----------
1 BMW 2
2 Audi 5
SQL> undefine prod
SQL> /
Enter value for prod: BETA
CAR_CODE CAR MODELS
---------- ---- ----------
3 Opel 0
SQL>
Depending on tool you use, that might be e.g. ... and :prod = 'ALPHA' or similar.
There's a good answer here that I think will help you:
Missing Keyword (ORA-00905) - Oracle SQL Case Statement
Check that out.
You can modify your sql statement as following:
SELECT CAR_CODE, CAR,
(CASE S.PROD
WHEN CASE S.PROD = 'ALPHA' THEN MODELS IN (2,3,4,5,6)
WHEN CASE S.PROD = 'BETA' THEN MODELS IN (0,1)
END
) MODELS
FROM TB_CAR_MODELS S

SQL query to sum separate columns with separate Where conditions

SQL noob here. I want to sum two columns separately, using 2 separate where conditions.
ID NAME VALUE1 VALUE2
--- ------- ------- -------
1 Orange 5 30
2 Orange 11 30
3 Orange 7 15
4 Pear 12 12
5 Pear 13 25
6 Pear 4 25
Sum of VALUE1 column where values are > 10
Sum of VALUE2 column where values are > 20
Grouped by NAME
Desired output:
NAME VALUE1 VALUE2
------- ------- -------
Orange 11 60
Pear 25 50
Thanks!
Use conditional aggregation:
select name, sum(case when value1 > 10 then value1 end),
sum(case when value2 > 20 then value2 end)
from t
group by name;
I know this approach is bit tricky and lengthy as well,however this might be helpful in debugging ,if you can try this :
select
value1.name,value1.a,value2.b
from
(select sum(value1)a,name from test where value1 >10 group by name) as value1
join (select sum(value2)b,name from test where value2 >20 group by name) as value2
on value1.name = value2.name

PL/SQL - SQL dynamic row and column parsing

I took a look into the forums and couldn't really find something that I needed.
What I have is two tables one table with (Parse_Table)
File_ID|Start_Pos|Length|Description
------------------------------------
1 | 1 | 9 | Pos1
1 | 10 | 1 | Pos2
1 | 11 | 1 | Pos3
2 | 1 | 4 | Pos1
2 | 5 | 7 | Pos2
and another table that needs to be parsed like (Input_file)
String
ABCDEFGHI12
ASRQWERTQ45
123456789AB
321654852PO
and I want to have the result where If I put it will use this specific parsing spec
select DESCRIPTION, Start_pos,Length from Parse_table where File_ID=1
and be able to parse input file
String | Pos1 |Pos2|Pos3
---------------------------------
ABCDEFGHI12 |ABCDEFGHI | 1 | 2
ASRQWERTQ45 |ASRQWERTQ | 4 | 5
123456789AB |123456789 | A | B
321654852PO |321654852 | P | O
and alternatively if I put file_id=2 it would parse the values differently.
I looked at using the Pivot function, but it looks like number of columns are static, at least to my knowledge.
thanks in advance for your support please let me know what I can do in SQL.
You can get "close-ish" with the standard decode tricks to pivot the table assuming a ceiling on the maximum number of fields expected.
SQL> create table t ( fid int, st int, len int, pos varchar2(10));
Table created.
SQL>
SQL> insert into t values ( 1 , 1 , 9 , 'Pos1');
1 row created.
SQL> insert into t values ( 1 , 10 , 1 , 'Pos2');
1 row created.
SQL> insert into t values ( 1 , 11 , 1 , 'Pos3');
1 row created.
SQL> insert into t values ( 2 , 1 , 4 , 'Pos1');
1 row created.
SQL> insert into t values ( 2 , 5 , 7 , 'Pos2');
1 row created.
SQL>
SQL> create table t1 ( s varchar2(20));
Table created.
SQL>
SQL> insert into t1 values ('ABCDEFGHI12');
1 row created.
SQL> insert into t1 values ('ASRQWERTQ45');
1 row created.
SQL> insert into t1 values ('123456789AB');
1 row created.
SQL> insert into t1 values ('321654852PO');
1 row created.
SQL>
SQL>
SQL> select
2 t1.s,
3 max(decode(t.seq,1,substr(t1.s,t.st,t.len))) c1,
4 max(decode(t.seq,2,substr(t1.s,t.st,t.len))) c2,
5 max(decode(t.seq,3,substr(t1.s,t.st,t.len))) c3,
6 max(decode(t.seq,4,substr(t1.s,t.st,t.len))) c4,
7 max(decode(t.seq,5,substr(t1.s,t.st,t.len))) c5,
8 max(decode(t.seq,6,substr(t1.s,t.st,t.len))) c6
9 from t1,
10 ( select t.*, row_number() over ( partition by fid order by st ) as seq
11 from t
12 where fid = 1
13 ) t
14 group by t1.s
15 order by 1;
S C1 C2 C3 C4 C5 C6
-------------------- ------------- ------------- ------------- ------------- ------------- -------------
123456789AB 123456789 A B
321654852PO 321654852 P O
ABCDEFGHI12 ABCDEFGHI 1 2
ASRQWERTQ45 ASRQWERTQ 4 5
4 rows selected.
SQL>
SQL> select
2 t1.s,
3 max(decode(t.seq,1,substr(t1.s,t.st,t.len))) c1,
4 max(decode(t.seq,2,substr(t1.s,t.st,t.len))) c2,
5 max(decode(t.seq,3,substr(t1.s,t.st,t.len))) c3,
6 max(decode(t.seq,4,substr(t1.s,t.st,t.len))) c4,
7 max(decode(t.seq,5,substr(t1.s,t.st,t.len))) c5,
8 max(decode(t.seq,6,substr(t1.s,t.st,t.len))) c6
9 from t1,
10 ( select t.*, row_number() over ( partition by fid order by st ) as seq
11 from t
12 where fid = 2
13 ) t
14 group by t1.s
15 order by 1;
S C1 C2 C3 C4 C5 C6
-------------------- ------------- ------------- ------------- ------------- ------------- -------------
123456789AB 1234 56789AB
321654852PO 3216 54852PO
ABCDEFGHI12 ABCD EFGHI12
ASRQWERTQ45 ASRQ WERTQ45
4 rows selected.
If you really wanted that result to then come back with only the desired column count and custom column names, then you're into dynamic SQL territory. How you'd tackle that depends on the tool you are providing the data to. If it can consume a REF CURSOR, then a little PL/SQL would do the trick.
An unknown number of columns can be returned from a SQL statement, but it requires code built with PL/SQL, ANY types, and Oracle Data Cartridge.
That code is tricky to write but you can start with my open source project Method4. Download, unzip, #install, and then
write a SQL statement to generate a SQL statement.
Query
select * from table(method4.dynamic_query(
q'[
--Create a SQL statement to query PARSE_FILE.
select
'select '||
listagg(column_expression, ',') within group (order by start_pos) ||
' from parse_file'
column_expressions
from
(
--Create individual SUBSTR column expressions.
select
parse_table.*,
'substr(string, '||start_pos||', '||length||') '||description column_expression
from parse_table
--CHANGE BELOW LINE TO USE A DIFFERENT FILE:
where file_id = 2
order by start_pos
)
]'
));
Sample Schema
create table parse_table as
select 1 file_id, 1 start_pos, 9 length, 'Pos1' description from dual union all
select 1 file_id, 10 start_pos, 1 length, 'Pos2' description from dual union all
select 1 file_id, 11 start_pos, 1 length, 'Pos3' description from dual union all
select 2 file_id, 1 start_pos, 4 length, 'Pos1' description from dual union all
select 2 file_id, 5 start_pos, 7 length, 'Pos2' description from dual;
create table parse_file as
select 'ABCDEFGHI12' string from dual union all
select 'ASRQWERTQ45' string from dual union all
select '123456789AB' string from dual union all
select '321654852PO' string from dual;
Results
When FILE_ID = 1:
POS1 POS2 POS3
---- ---- ----
ABCDEFGHI 1 2
ASRQWERTQ 4 5
123456789 A B
321654852 P O
When FILE_ID = 2:
POS1 POS2
---- ----
ABCD EFGHI12
ASRQ WERTQ45
1234 56789AB
3216 54852PO

Update statement using current value of the table

I want to update a row in a table by incrementing by one the integer value of one of the field..
The current doesn't work, why?
Update htmIndex SET numObs = numObs+1 where ...
Simple case, update one row:
SQL> select name
2 , age
3 from t23
4 where id = 2
5 /
NAME AGE
------------ ----------
MR KNOX 47
SQL> update t23
2 set age = age + 6
3 where id = 2
4 /
1 row updated.
SQL> select name
2 , age
3 from t23
4 where id = 2
5 /
NAME AGE
------------ ----------
MR KNOX 53
SQL>
Update a row when the column has a null value:
SQL> select name
2 , age
3 from t23
4 where id = 6
5 /
NAME AGE
------------ ----------
SALLY
SQL> update t23
2 set age=age+5
3 where id = 6
4 /
1 row updated.
SQL> select name
2 , age
3 from t23
4 where id = 6
5 /
NAME AGE
------------ ----------
SALLY
SQL> update t23
2 set age = nvl(age,0) +5
3 where id = 6
4 /
1 row updated.
SQL> select name
2 , age
3 from t23
4 where id = 6
5 /
NAME AGE
------------ ----------
SALLY 5
SQL>
Equally straightforward when updating multiple rows:
SQL> select name
2 , age
3 from t23
4 where age > 20
5 /
NAME AGE
------------ ----------
MR KNOX 53
FOX IN SOCKS 37
CAT 23
LORAX 443
SQL> update t23
2 set age = age + 1
3 where age > 20
4 /
4 rows updated.
SQL> select name
2 , age
3 from t23
4 where age > 20
5 /
NAME AGE
------------ ----------
MR KNOX 54
FOX IN SOCKS 38
CAT 24
LORAX 444
SQL>
It should work. However if the current column value is null then + 1 will return null.
try: Update htmIndex SET numObs = nvl(numObs,0)+1 where ...