Need oracle query to select the order by - oracle

Table contains value 1,2,3 but while display the values needs to show 2,1,3
Example
Table A
column1 column2 column3
1 Rat Animals
2 Parrot Bird
3 Lotus Flower
Need to display parrot first then Rat and Lotus which means 2,1,3
Expected Output:
column1 column2 column3
2 Parrot Bird
1 Rat Animal
3 Lotus Flower
Kindly help me out to fix the issue in order by query.

You could use CASE expression in the ORDER BY clause for the particular conditions, and let other rows retain their order.
Setup
SQL> CREATE TABLE t
2 (column1 int, column2 varchar2(6), column3 varchar2(7));
Table created.
SQL> INSERT ALL
2 INTO t (column1, column2, column3)
3 VALUES (1, 'Rat', 'Animals')
4 INTO t (column1, column2, column3)
5 VALUES (2, 'Parrot', 'Bird')
6 INTO t (column1, column2, column3)
7 VALUES (3, 'Lotus', 'Flower')
8 INTO t (column1, column2, column3)
9 VALUES (7, 'def', 'xyz')
10 INTO t (column1, column2, column3)
11 VALUES (4, 'abc', 'qwe')
12 SELECT * FROM dual;
5 rows created.
SQL> COMMIT;
Commit complete.
Table Data
SQL> SELECT * FROM t;
COLUMN1 COLUMN COLUMN3
---------- ------ -------
1 Rat Animals
2 Parrot Bird
3 Lotus Flower
7 def xyz
4 abc qwe
Required Query
SQL> SELECT * FROM t
2 ORDER BY
3 CASE column1
4 WHEN 1
5 THEN 2
6 WHEN 2
7 THEN 1
8 ELSE 3
9 END,
10 column1;
COLUMN1 COLUMN COLUMN3
---------- ------ -------
2 Parrot Bird
1 Rat Animals
3 Lotus Flower
4 abc qwe
7 def xyz
SQL>
So, you have your desired order as well as the other rows retain their order as specified.

That is a strange order requested, anyways try this -
SELECT Column1,Column2,Column3
FROM TableA
ORDER BY CASE WHEN Column1 = 2 THEN 1
WHEN Column1 = 1 THEN 2
ELSE 3
END

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.

Insert record from one table to another table - Oracle

I have a table TABLE1 which has 5 columns (ROLL_NO, NAME, UNITS, CODE, AMOUNT);
CREATE TABLE TABLE1 (ROLL_NO VARCHAR2(3), NAME VARCHAR2(4), UNITS NUMBER, AMOUNT NUMBER, CODE VARCHAR2(3));
------------------------------------------------------------------------------------------
INSERT INTO TABLE1 VALUES ('101', 'JOHN', 1, 6, 'ABC');
INSERT INTO TABLE1 VALUES ('101', 'JOHN', 2, 6, 'ABC');
INSERT INTO TABLE1 VALUES ('102', 'TOMS', 1, 7, 'ABC');
INSERT INTO TABLE1 VALUES ('102', 'TOMS', 6, 7, 'ABC');
INSERT INTO TABLE1 VALUES ('103', 'FINN', 1, 1, 'BCD');
ROLL_NO NAME UNITS AMOUNT CODE
-------------------------------------------------------
101 JOHN 1 6 ABC
101 JOHN 2 6 ABC
-------------------------------------------
102 TOMS 1 7 ABC
102 TOMS 6 7 ABC
103 FINN 1 1 BCD
There is second table TABLE2 where we need to insert data from TABLE1
CREATE TABLE TABLE2 (ROLL_NO VARCHAR2(3), NAME VARCHAR2(4), RESULT VARCHAR2(3));
There are three conditions to insert data into TABLE2
1st case : If CODE is 'ABC' and SUM(UNITS) of particular ROLL_NO is equal to AMOUNT then don't insert data into TABLE2
2nd case : If CODE is 'ABC' and SUM(UNITS) of particular ROLL_NO is not equal to AMOUNT then insert data with RESULT column value as 'YES'
3rd case : If CODE is not 'ABC' then RESULT column will be 'YES'.
Note: NAME, CODE and AMOUNT will be same for particular ROLL_NO though ROLL_NO has multiple UNITS.
Example :
ROLL_NO 102 CODE 'ABC' and two lines with SUM(UNITS) as 7 and its equal to AMOUNT i.e. 7 and (1st case)
ROLL_NO 101 has CODE 'ABC' and two lines with SUM(UNITS) as 3 and its not equal to AMOUNT i.e. 6 (2nd case)
ROLL_NO 103 has CODE 'BCD' which is not equal to 'ABC'(3rd case)
At the end TABLE2 should have
ROLL_NO NAME RESULT
-----------------------------
101 JOHN YES
103 FINN YES
I have tried this oracle query but it is inserting data related to 102 ROLL_NO which I don't need
SELECT T1.ROLL_NO, T1.NAME,
CASE
WHEN T1.CODE <> 'ABC' THEN 'YES'
WHEN T1.CODE = 'ABC' AND T2.TOT_UNITS <> T1.AMOUNT THEN 'YES'
END RESULT
FROM (SELECT DISTINCT ROLL_NO, NAME, AMOUNT, CODE
FROM TABLE1 ) T1
JOIN (SELECT ROLL_NO, SUM(UNITS) AS TOT_UNITS
FROM TABLE1
GROUP BY ROLL_NO) T2 ON T1.ROLL_NO = T2.ROLL_NO
I am not able to figure out how to not insert ROLL_NO 102 record into TABLE2..Can anyone provide better query than this if possible? Thank you
A "better" option is to scan table1 only once.
SQL> insert into table2 (roll_no, name, result)
2 with temp as
3 (select roll_no, name, sum(units) sum_units, amount, code,
4 case when code = 'ABC' and sum(units) = amount then 'NO'
5 when code = 'ABC' and sum(units) <> amount then 'YES'
6 else 'YES'
7 end as result
8 from table1
9 group by roll_no, name, amount, code
10 )
11 select roll_no, name, result
12 from temp
13 where result = 'YES';
2 rows created.
SQL> select * from table2;
ROL NAME RES
--- ---- ---
101 JOHN YES
103 FINN YES
SQL>

Merge - Oracle and populate in two different tables based on count condition

I have a table name "TABLE1" with 4 columns COLUMN1, COLUMN2, FREQ, CNT
I have a result table name "RESULT1" with 4 columns COLUMN1, COLUMN2, FREQ
I have a result table name "RESULT2" with 4 columns COLUMN1, COLUMN2, FREQ
CREATE TABLE TABLE1 ( COLUMN1 VARCHAR2(4), COLUMN2 VARCHAR2(4), FREQ NUMBER, CNT NUMBER);
INSERT INTO TABLE1(COLUMN1, COLUMN2, FREQ) VALUES ('1234', 'ABCD', 1);
INSERT INTO TABLE1(COLUMN1, COLUMN2, FREQ) VALUES ('1234', 'ACBD', 1);
INSERT INTO TABLE1(COLUMN1, COLUMN2, FREQ) VALUES ('1234', 'ABDC', 1);
INSERT INTO TABLE1(COLUMN1, COLUMN2, FREQ) VALUES ('1342', 'DAFY', 1);
INSERT INTO TABLE1(COLUMN1, COLUMN2, FREQ) VALUES ('1423', 'CBAD', 1);
I want to update the CNT column in TABLE1 based on number of times COLUMN1 is repeated.
The result in TABLE1:
COLUMN1 COLUMN2 FREQ CNT
-----------------------------------
1234 ABCD 1 3
1234 ACBD 1 3
1234 ABDC 1 3
1342 DAFY 1 1
1423 CBAD 1 1
Once we get above result,
based on CNT value, if CNT =1 insert in RESULT1 table else CNT > 1 insert those records in RESULT2 table like
RESULT2 table
COLUMN1 COLUMN2 FREQ
-----------------------------------
1234 ABCD 1
1234 ACBD 1
1234 ABDC 1
RESULT1 table
COLUMN1 COLUMN2 FREQ
-----------------------------------
1342 DAFY 1
1423 CBAD 1
I tried using MERGE statement to populate but not able to get answer showing some syntax error.
how about the oracle insert all. lets you insert into multiple tables based on a condition.
insert All
When cnt > 1 THEN
into result1
else
into result2
select column1, column2, freq, count(*) over (partition by column1) as cnt from table1;
here is the sql fiddle. http://sqlfiddle.com/#!4/d6f20/5
From my point of view, a simple way is the best way.
This is the starting point:
SQL> select * from table1;
COLU COLU FREQ CNT
---- ---- ---------- ----------
1234 ABCD 1
1234 ACBD 1
1234 ABDC 1
1342 DAFY 1
1423 CBAD 1
Update TABLE1.CNT:
SQL> update table1 a set
2 a.cnt = (select count(*)
3 from table1 b
4 where b.column1 = a.column1
5 );
5 rows updated.
SQL> select * from table1;
COLU COLU FREQ CNT
---- ---- ---------- ----------
1234 ABCD 1 3
1234 ACBD 1 3
1234 ABDC 1 3
1342 DAFY 1 1
1423 CBAD 1 1
Rows whose cnt = 1 go into result1:
SQL> insert into result1 (column1, column2, freq)
2 select column1, column2, freq
3 from table1
4 where cnt = 1;
2 rows created.
SQL> select * from result1;
COLU COLU FREQ
---- ---- ----------
1342 DAFY 1
1423 CBAD 1
Rows whose cnt > 1 go into result2:
SQL> insert into result2 (column1, column2, freq)
2 select column1, column2, freq
3 from table1
4 where cnt > 1;
3 rows created.
SQL> select * from result2;
COLU COLU FREQ
---- ---- ----------
1234 ABCD 1
1234 ACBD 1
1234 ABDC 1
SQL>
The end.

Retrieving based on specific condition

I have a little complex requirement on couple of tables which I am finding hard to crack.
There are 2 tables. TableA and TableB
TableA has a structure like:
-------------------------------------
ID COL1 COL2 CAT
-------------------------------------
1 RecAA RecAB 3
2 RecBA RecBB 3
3 RecCA RecCB 2
4 RecDA RecDB 2
5 RecEA RecEB 1
-------------------------------------
TableB has a structure like:
-----------------
COL3 TYPE
-----------------
RecAA 10
RecAA 11
RecAA 12
RecAB 10
RecAB 11
RecAB 12
RecAB 13
RecAB 14
RecBA 10
RecBA 11
RecBA 14
RecBA 15
RecBB 10
-----------------
Requirements:
Records in TableA should have CAT = 3.
Either COL1 or COL2 of TableA should be available in COL3 of TableB.
COL3 should definitely have TYPE in 10,11,12 and should have only that TYPE.
i.e As per the above requirements,
Of the records available in TableA, records with ID 1 and 2 have CAT = 3 in TableA
Both the records have atleast only value in COL3 of TableB. (Record with ID 1 in TableA has both COL1 and COL2 in TableB and record with ID 2 in TableA has COL1 in TableB)
RecAA record has Type 10,11,12 and only 10,11,12. So doesnt matter if RecAB has 10,11,12 or not. But RecBA and RecBB both does not have 10,11,12 types.
Therefore the result should be:
-------------------------------------
ID COL1 COL2 CAT
-------------------------------------
1 RecAA RecAB 3
-------------------------------------
What I tried:
WITH TEMP AS (SELECT COL3 FROM TableB GROUP BY COL3 HAVING SUM(CASE WHEN TYPE IN ('10','11','12') THEN 1 ELSE 0 END) = 0)
SELECT S.ID, S.COL1, S.COL2, S.CAT FROM TableA S
INNER JOIN TEMP T ON S.COL1 = T.COL3
WHERE S.CAT = 3;
Can someone please help on achieving this?
I think you're almost there, it's just your row selection in the CTE that seems problematic, and I think you need an OR:
WITH TEMP AS (
SELECT COL3
FROM TableB
GROUP BY COL3
HAVING SUM(POWER(2, TYPE - 10)) = 7 AND COUNT(*) = 3
)
SELECT
S.ID, S.COL1, S.COL2, S.CAT
FROM
TableA S
INNER JOIN TEMP T ON S.COL1 = T.COL3 OR S.COL2 = T.COL3
WHERE
S.CAT = 3;
I've subtracted 10 from each of your TYPEs to turn your 10,11,12 into 0,1,2 and then used POWER to turn them into 1, 2 and 4 which uniquely sum to 7 - (in other words your 10,11,12 became 2^(10-10), 2^(11-10) and 2^(12-10) which are 1, 2 and 4.. Which must then sum to 7).
I also mandate that there be a count of 3; the only way to get to 7 with three numbers that are powers of 2 is to have 1+2+4 which guarantees that 10,11,12 are present initially. If anything was missing, extra or repeated it wouldn't be 3 numbers that sum to 7
I think RecAB is excluded because even though it has 10,11,12 it also has 13,14 which cause it to be excluded..
You also seemed to be saying that COL3 should be present in either COL1 or COL2 of table A
You can use listagg analytic version to turn TYPE column into type_in_list column like below :
With temp_TableB (COL3, type_in_list) as (
SELECT distinct COL3, listagg(TYPE, ',') within group (order by TYPE)over(partition by COL3)
FROM TableB
)
select tA.*
--, tb.*
from tableA tA
INNER JOIN temp_TableB tB on (tA.COL1 = tB.COL3 or tA.COL2 = tB.COL3)
Where tA.CAT = 3
AND tB.TYPE_IN_LIST = '10,11,12'
;

Oracle update from random on another table

I have some fields in table1 to update with random values from some fields in table2.
I have to random into rows of table2 and update each rows of table1 with the same rows values of table2.
Here is my SQL code, but it doesn't work.
update owner.table1 t1
set (t1.adress1, t1.zip_code, t1.town) = (select t2.adress, t2.zip_code, t2.town
from table1 t2
where id = trunc(dbms_random.value(1,20000)))
Result: all rows are updated with the same values, like no random on table 2 rows
How about switching to analytic ROW_NUMBER function? It doesn't really create a random value, but might be good enough.
Here's an example: first, create test tables and insert some data:
SQL> create table t1 (id number,address varchar2(20), town varchar2(10));
Table created.
SQL> create table t2 (id number, address varchar2(20), town varchar2(10));
Table created.
SQL> insert into t1
2 select 1, 'Ilica 20', 'Zagreb' from dual union all
3 select 2, 'Petrinjska 30', 'Sisak' from dual union all
4 select 3, 'Stradun 12', 'Dubrovnik' from dual;
3 rows created.
SQL> insert into t2
2 select 1, 'Pavelinska 15', 'Koprivnica' from dual union all
3 select 2, 'Baščaršija 11', 'Sarajevo' from dual union all
4 select 3, 'Riva 22', 'Split' from dual;
3 rows created.
SQL> select * From t1 order by id;
ID ADDRESS TOWN
---------- -------------------- ----------
1 Ilica 20 Zagreb
2 Petrinjska 30 Sisak
3 Stradun 12 Dubrovnik
SQL> select * From t2 order by id;
ID ADDRESS TOWN
---------- -------------------- ----------
1 Pavelinska 15 Koprivnica
2 Baščaršija 11 Sarajevo
3 Riva 22 Split
Update t1 with rows from t2:
SQL> update t1 set
2 (t1.address, t1.town) =
3 (select x.address, x.town
4 from (select row_number() over (order by address) id, t2.address, t2.town
5 from t2
6 ) x
7 where x.id = t1.id);
3 rows updated.
SQL> select * From t1 order by id;
ID ADDRESS TOWN
---------- -------------------- ----------
1 Baščaršija 11 Sarajevo
2 Pavelinska 15 Koprivnica
3 Riva 22 Split
SQL>

Resources