Dynamically update null columns with the target values - oracle

Need to update columns which have null in column, with the target values
COL3 - DATE DATATYPE
COL1,2,4 - NUMBER DATATYPE
EXAMPLE
TABLE
COL1 COL2 COL3 COL4
1 2 29-02-22 NULL
1 NULL 29-02-22 4
2 4 29-02-22 8
3 NULL NULL 55
4 5 29-02-22 NULL
5 5 29-02-22 44
5 6 29-02-22 4
5 NULL NULL NULL
OUTPUT
COL1 COL2 COL3 COL4
1 2 29-02-22 30
1 3 29-02-22 4
2 4 29-02-22 8
3 5 29-02-22 55
4 5 29-02-22 33
5 5 29-02-22 44
5 6 29-02-22 4
5 1 29-02-22 2
How to compare null and replace it with the value. Tried Decode and Case in the update statement, however, Haven't got any solution. The main purpose is to update the null value with the target value. The example illustrates to show what will be the source and how output will looks like

You can use the COALESCE function. COALESCE returns the first non-null argument in the list.
UPDATE myTable
SET
Col1 = COALESCE(Col1, col1_targetValue),
Col2 = COALESCE(Col2, col2_targetValue),
Col3 = COALESCE(Col3, col3_targetValue),
Col4 = COALESCE(Col4, col4_targetValue)
This will replace the NULL values in all rows. Add an appropriate WHERE clause to update only specific rows.

Related

how to convert column value to multiple insert rown oracle cursor

I am trying to copy value from our old db to new db where there is a change in the table structure.
Below is the structure of the table
Table1
Table1ID, WheelCount, BlindCount, OtherCount
For eg values of table 1 is like below
Table1ID, 1,2,5
Table1 is now changed to TableNew with the below
TableNewID, DisableID , Quantity.
So the value should be
TableNewID1, 1,1 here 1= WheelCount from table1
TableNewID2, 2,2 here 2= BlindCount
TableNewID3, 3,5 here 5= OtherCount
how to write a cursor to transform table1 value to the new table tableNew structure.
Table1
Table1ID WheelCount BlindCount OtherCount
1 1 2 5
2 8 10 15
A master table defined to map disableid
DisableID Type
1 wheelCount
2 blindcount
3 otherCount
Expected structure
ID **Table1ID** **DISABLEID** QUANTITY
1 1 1 1
2 1 2 2
3 1 3 5
4 2 1 8
5 2 2 10
6 2 3 15
The simplest is a UNION ALL for each column you want to turn into a row.
insert into tablenew
select table1id,1,wheelcount from table1
union all
select table1id,2,blindcount from table1
union all
select table1id,3,othercount from table1
There are other, sleeker methods for avoiding multiple passes on the first table, in case it's huge.
This is how I understood it.
Current table contents:
SQL> SELECT * FROM table1;
TABLE1ID WHEELCOUNT BLINDCOUNT OTHERCOUNT
---------- ---------- ---------- ----------
1 1 2 5
2 8 10 15
Prepare new table:
SQL> CREATE TABLE tablenew
2 (
3 id NUMBER,
4 table1id NUMBER,
5 disableid NUMBER,
6 quantity NUMBER
7 );
Table created.
Sequence (will be used to populate tablenew.id column):
SQL> CREATE SEQUENCE seq_dis;
Sequence created.
Trigger (which actually populates tablenew.id):
SQL> CREATE OR REPLACE TRIGGER trg_bi_tn
2 BEFORE INSERT
3 ON tablenew
4 FOR EACH ROW
5 BEGIN
6 :new.id := seq_dis.NEXTVAL;
7 END;
8 /
Trigger created.
Copy data:
SQL> INSERT INTO tablenew (table1id, disableid, quantity)
2 SELECT table1id, 1 disableid, wheelcount AS quantity FROM table1
3 UNION ALL
4 SELECT table1id, 2 disableid, blindcount AS quantity FROM table1
5 UNION ALL
6 SELECT table1id, 3 disableid, othercount AS quantity FROM table1;
6 rows created.
Result:
SQL> SELECT *
2 FROM tablenew
3 ORDER BY table1id, disableid;
ID TABLE1ID DISABLEID QUANTITY
---------- ---------- ---------- ----------
1 1 1 1
3 1 2 2
5 1 3 5
2 2 1 8
4 2 2 10
6 2 3 15
6 rows selected.

PL/SQL Oracle :- Dynamically UNPIVOT ORACLE TABLE on passing a value

I have a table as below with data:-
Item COL1 COL2 COL3 COL4 COL5 COL6 .... COL 30
A 1 1 2 3 4 2 5 2
B 2 6 4 3 5 2 5 1
C 3 4 5 2 2 2 4 2
D 4 5 2 23 45 3 3 3
F 5 3 1 11 23 34 34 1
and need to UNPIVOT depending on the value I give... If I give 4, the table is unpivoted to COL4, If I give 7 the table is unpivoted till 7, making it dynamic. I have written a simple SQL but cant get a way to make it dynamic
SELECT * FROM (
WITH
WIDE AS (
SELECT
/*+ PARALLEL(128) */
ITEM, COL1, COL2, COL3, COL4, COL5, COL6, COL7
FROM TAB
WHERE ITEM = 'A'
)
SELECT
/*+ PARALLEL(128) */
ITEM
FROM WIDE
UNPIVOT INCLUDE NULLS
(QTY FOR SCOL IN
(COL1, COL2, COL3, COL4, COL5, COL6,
COL7
)
)
);
Why don't you unpivot all possible columns and then restrict the dataset with the where clause:
SELECT ITEM, SCOL, QTY
FROM WIDE
UNPIVOT INCLUDE NULLS
(QTY FOR SCOL IN (COL1, ..., COL 30))
WHERE TO_NUMBER(SUBSTR(SCOL,4)) <= 7 -- 7 Should be replaced with your parameter

How to filter 1 column on 'unique', and second column on 'most occuring' in Google Spreadsheets

I want to filter 2 large columns in Google Spreadsheets.
The outcome from column 1 must only show the unique values
The outcome from column 2 must show the most occuring value for each unique value from 1.
Example dataset:
NL 1
NL 1
NL 2
NL 3
BE 2
BE 2
BE 4
BE 2
USA 6
USA 5
USA 6
USA 6
FR 5
FR 4
FR 2
FR 3
FR 1
FR 2
LUX 2
the outcome would be:
NL 1
BE 2
USA 6
FR 2
LUX 2
The formula is:
=ArrayFormula(VLOOKUP(UNIQUE(FILTER(A:A,A:A<>"")),QUERY({A:B,A:A},"select Col1, Col2, count(Col3) where Col1 <> '' group by Col1, Col2 order by count(Col3) desc"),{1,2},0))
Sample file:
https://docs.google.com/spreadsheets/d/1LwRiKACY4Myp_1NtkFkvtTy1xRvNPx0u5e-Pi0SuzGI/edit?usp=sharing
If your local settings differs from the US then use formula:
=ArrayFormula(VLOOKUP(UNIQUE(FILTER(A:A;A:A<>""));QUERY({A:B\A:A};"select Col1, Col2, count(Col3) where Col1 <> '' group by Col1, Col2 order by count(Col3) desc");{1\2};0))
The number of times some values occur
This part of formula is counting all the data, putting the most frequent to the top:
QUERY({A:B,A:A},"select Col1, Col2, count(Col3) where Col1 <> '' group by Col1, Col2 order by count(Col3) desc")

How do you shift values down in a column in an Oracle table?

Given the following oracle database table:
group revision comment
1 1 1
1 2 2
1 null null
2 1 1
2 2 2
2 3 3
2 4 4
2 null null
3 1 1
3 2 2
3 3 3
3 null null
I want to shift the comment column one step down in relation to version, within its group, so that I get the following table:
group revision comment
1 1 null
1 2 1
1 null 2
2 1 null
2 2 1
2 3 2
2 4 3
2 null 4
3 1 null
3 2 1
3 3 2
3 null 3
I have the following query:
MERGE INTO example_table t1
USING example_table t2
ON (
(t1.revision = t2.revision+1 OR
(t2.revision = (
SELECT MAX(t3.revision)
FROM example_table t3
WHERE t3.group = t1.group
) AND t1.revision IS NULL)
)
AND t1.group = t2.group)
WHEN MATCHED THEN UPDATE SET t1.comment = t2.comment;
That does most of this (still need a separate query to cover revision = 1), but it is very slow.
So my question is, how do I use Max here as efficiently as possible to pull out the highest revision for each group?
I would use lag not max
create table example_table(group_id number, revision number, comments varchar2(40));
insert into example_table values (1,1,1);
insert into example_table values (1,2,2);
insert into example_table values (1,3,null);
insert into example_table values (2,1,1);
insert into example_table values (2,2,2);
insert into example_table values (2,3,3);
insert into example_table values (2,4,null);
select * from example_table;
merge into example_table e
using (select group_id, revision, comments, lag(comments, 1) over (partition by group_id order by revision nulls last) comments1 from example_table) u
on (u.group_id = e.group_id and nvl(u.revision,0) = nvl(e.revision,0))
when matched then update set comments = u.comments1;
select * from example_table;

Hive - Split delimited columns over multiple rows, select based on position

I'm Looking for a way to split the column based on comma delimited data. Below is my dataset
id col1 col2
1 5,6 7,8
I want to get the result
id col1 col2
1 5 7
1 6 8
The position of the index should match because I need to fetch results accordingly.
I tried the below query but it returns the cartesian product.
Query:
SELECT col3, col4
FROM test ext
lateral VIEW explode(split(col1,'\002')) col1 AS col3
lateral VIEW explode(split(col2,'\002')) col2 AS col4
Result:
id col1 col2
1 5 7
1 5 8
1 6 7
1 6 8
You can use posexplode() to create position index columns for your split arrays. Then, select only those rows where the position indices are equal.
SELECT id, col3, col4
FROM test
lateral VIEW posexplode(split(col1,'\002')) col1 AS pos3, col3
lateral VIEW posexplode(split(col2,'\002')) col2 AS pos4, col4
WHERE pos3 = pos4;
Output:
id col3 col4
1 5 7
1 6 8
Reference: Hive language manual - posexplode()

Resources