1 .Generate
numbers/sequence using dual with a specific interval.
1 
2 
3 
 | 
  
SELECT *
  FROM (SELECT CASE
  WHEN MOD(LEVEL,4)=1
  THEN LEVEL END
  seq FROM dual 
CONNECT BY LEVEL <=100) 
WHERE   seq IS NOT
  NULL 
 | 
 
This is generate numbers
with interval of 4.
1
5
9
13
…
1 
2 
3 
 | 
  
SELECT *
  FROM (SELECT CASE
  WHEN MOD(LEVEL,5)=1
  THEN LEVEL END
  seq FROM dual 
CONNECT BY LEVEL <=100) 
WHERE   seq IS NOT
  NULL 
 | 
 
This is generate numbers
with interval of 5.
1
6
11
16
…
To generate multiples of a number using dual in ORACLE.
1 
2 
 | 
  
SELECT LEVEL*3
  FROM dual 
CONNECT BY LEVEL <=20 
 | 
 
This will generate
multiples of 3..
SEQ
3
6
9
12
…..
****************************************************
2. The next question is
on triggers. There are 4 columns in a table, marks1, marks2,marks3 and total.
The trigger should calculate the total and update the total when
we insert marks1, marks2 and marks3.
To create the table:
1 
2 
 | 
  
create table test_marks(subject
  varchar2(10), 
marks1 number,
  marks2 number, marks3 number, total number) 
 | 
 
On insert, the trigger
should automatically calculate the sum of marks1, marks2 and marks3 and assign
it to total column:
1 
2 
 | 
  
INSERT INTO test_marks(subject,marks1,marks2,marks3) 
VALUES ('A1',12,13,14); 
 | 
 
Answer :
trigger
to update the value of total as sum of marks1, marks2, marks3
1 
2 
3 
4 
5 
 | 
  
CREATE OR REPLACE TRIGGER find_total 
BEFORE  INSERT ON test_marks
  FOR EACH ROW 
BEGIN 
:new.total :=
  :new.marks1+:new.marks2+:new.marks3; 
END; 
 | 
 
;
Note: AFTER INSERT will
not work in this case.
****************************************************
3. How I understood this
query which orders by based on the ‘number part’ .
1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
13 
14 
 | 
  
create table ting(tno
  varchar2(4)); 
insert into ting
  values('1'); 
insert into ting
  values('2'); 
insert into ting
  values('3'); 
insert into ting
  values('10'); 
insert into ting
  values('11'); 
insert into ting
  values('1a'); 
insert into ting
  values('20'); 
insert into ting
  values('2a'); 
insert into ting
  values('3a'); 
insert into ting
  values('10a'); 
insert into ting
  values('10b'); 
insert into ting
  values('31b'); 
insert into ting
  values('31'); 
 | 
 
1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
13 
14 
15 
16 
17 
18 
19 
 | 
  
SQL> SELECT *
  FROM ting; 
TNO 
---- 
1 
2 
3 
10 
11 
1a 
20 
2a 
3a 
10a 
10b 
31b 
31 
13 rows selected 
 | 
 
The final solution is
provided at the end. You can skip the following sections and directly go for
the final solution. The following steps are a breakdown of the final solution.
This is how I understood the final query.
Step 1. Replace all the digit
with 0 using translate.
1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
13 
14 
15 
16 
17 
18 
19 
 | 
  
SQL> SELECT translate(tno,'0123456789','000000000')
  FROM ting; 
TRANSLATE(TNO,'0123456789','00 
------------------------------ 
0 
0 
0 
00 
00 
0a 
00 
0a 
0a 
00a 
00b 
00b 
00 
13 rows selected 
 | 
 
Step 2. Now replace the 0 with
null.
1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
13 
14 
15 
16 
17 
18 
19 
 | 
  
SQL> SELECT translate(tno,'0123456789','000000000')
  q,REPLACE(translate(tno,'0123456789','000000000'),'0','') FROM ting; 
Q   
  REPLACE(TRANSLATE(TNO,'0123456 
----
  ------------------------------ 
0 
0 
0 
00 
00 
0a   a 
00 
0a   a 
0a   a 
00a  a 
00b  b 
00b  b 
00    
13 rows selected 
 | 
 
Step 3. Next we find the length
of the values which are not null(with alphabets). Gives 1
1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
13 
14 
15 
16 
17 
18 
19 
 | 
  
SQL> SELECT translate(tno,'0123456789','000000000')
  q,length(REPLACE(translate(tno,'0123456789','000000000'),'0','')) FROM ting; 
Q   
  LENGTH(REPLACE(TRANSLATE(TNO,' 
----
  ------------------------------ 
0 
0 
0 
00 
00 
0a                               
  1 
00 
0a                               
  1 
0a                               
  1 
00a                              
  1 
00b                              
  1 
00b                              
  1 
00    
13 rows selected 
 | 
 
Step 4. Find the total length
(length(tno))of the string and using NVL replace the null values in the above
query with 0.
1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
13 
14 
15 
16 
17 
18 
19 
 | 
  
SQL> SELECT tno,length(tno),nvl(length(REPLACE(translate(tno,'0123456789','000000000'),'0','')),0)
  FROM ting; 
TNO 
  LENGTH(TNO) NVL(LENGTH(REPLACE(TRANSLATE(T 
---- -----------
  ------------------------------ 
1             
  1                             
  0 
2             
  1                             
  0 
3             
  1                             
  0 
10            
  2                             
  0 
11            
  2                             
  0 
1a            
  2                             
  1 
20            
  2                             
  0 
2a            
  2                             
  1 
3a            
  2                             
  1 
10a           
  3                             
  1 
10b           
  3                             
  1 
31b           
  3                             
  1 
31            
  2                             
  0 
13 rows selected 
 | 
 
Step 5. Use substr to extract
only the digits from tno using 1 as start index and the difference between
length(tno)
-nvl(length(REPLACE(translate(tno,’0123456789′,’000000000′),’0′,”)),0) as the
end index. This gives the first column in the final query (A)
1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
13 
14 
15 
16 
17 
18 
19 
 | 
  
SQL> SELECT substr(tno,1,length(tno)-nvl(length(REPLACE(translate(tno,'0123456789','000000000'),'0','')),0))
  a FROM ting; 
A 
---- 
1 
2 
3 
10 
11 
1 
20 
2 
3 
10 
10 
31 
31 
13 rows selected 
 | 
 
Step 6. Use substr to display
only the alphabets. Add 1 to the end_index in the above query and take it as
the start index. (I have added rownum here to show the rows with null values.)
This is the second row in the final query (B).
1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
13 
14 
15 
16 
17 
18 
19 
20 
 | 
  
SQL> SELECT rownum, 
substr(tno,length(tno)-nvl(length(REPLACE(translate(tno,'0123456789','000000000'),'0','')),0)+1)
  b FROM ting; 
    ROWNUM
  B 
---------- ---- 
         1 
         2 
         3 
         4 
         5 
         6
  a 
         7 
         8
  a 
         9
  a 
        10
  a 
        11
  b 
        12
  b 
        13
   
13 rows selected 
 | 
 
Step 7. Here I am just
displaying the two columns we created earlier. Column A in step 5 and column B
in step 6 along with the original column tno.
1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
13 
14 
15 
16 
17 
18 
19 
20 
21 
22 
 | 
  
SQL> SELECT substr(tno,1,
  length(tno)-nvl(length(replace(translate(tno,'0123456789','0000000000'),'0','')),0))
  a, 
  2  
  substr(tno,length(tno)-nvl(length(replace(translate(tno,'0123456789','0000000000'),'0','')),0)
  +1 ) b, 
  3  
  tno 
  4  
  FROM ting; 
A   
  B    TNO 
---- ---- ---- 
1        
  1 
2        
  2 
3        
  3 
10       
  10 
11       
  11 
1   
  a    1a 
20       
  20 
2   
  a    2a 
3   
  a    3a 
10  
  a    10a 
10  
  b    10b 
31  
  b    31b 
31       
  31 
13 rows selected 
 | 
 
Step 8. The final solution . Try
running the query without using NULLS FIRST and you will know the reason it has
been kept there.
1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
13 
14 
15 
16 
17 
18 
19 
20 
21 
22 
23 
24 
25 
26 
 | 
  
SQL> SELECT substr(tno,1,
  length(tno)-nvl(length(replace(translate(tno,'0123456789','0000000000'),'0','')),0))
  a, 
  2 
  substr(tno,length(tno)-nvl(length(replace(translate(tno,'0123456789','0000000000'),'0','')),0)
  +1 ) b, 
  3 
  tno 
  4 
  FROM ting 
  5 
  ORDER BY to_number(a),b NULLS FIRST 
  6 
  ; 
A   
  B    TNO 
---- ---- ---- 
1        
  1 
1   
  a    1a 
2        
  2 
2   
  a    2a 
3        
  3 
3   
  a    3a 
10       
  10 
10  
  a    10a 
10  
  b    10b 
11       
  11 
20       
  20 
31       
  31 
31  
  b    31b 
13 rows selected 
SQL> 
 | 
 
****************************************************
4. How will you insert
multiple rows of dummy data into a date column or a varchar2 column?
This query can be used to “fill” an empty table with date datatype column.
1 
2 
3 
 | 
  
SELECT sysdate,level-1
  lv,7*(LEVEL-1) s, 
trunc(SYSDATE-(7*(LEVEL-1)))
  t FROM dual 
CONNECT BY LEVEL <
  10; 
 | 
 
This query uses the
LEVEL pseudo-column to get dates with an interval of 7 days.
1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
 | 
  
SYSDATE       
  LV  S   T 
7/5/2011 5:22:14 PM
  0   0   7/5/2011 
7/5/2011 5:22:14 PM
  1   7   6/28/2011 
7/5/2011 5:22:14 PM
  2   14  6/21/2011 
7/5/2011 5:22:14 PM
  3   21  6/14/2011 
7/5/2011 5:22:14 PM
  4   28  6/7/2011 
7/5/2011 5:22:14 PM
  5   35  5/31/2011 
7/5/2011 5:22:14 PM
  6   42  5/24/2011 
7/5/2011 5:22:14 PM
  7   49  5/17/2011 
7/5/2011 5:22:14 PM
  8   56  5/10/2011    
 | 
 
Another example to get
dates with an interval of 3 days.
1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
13 
14 
 | 
  
SELECT trunc(SYSDATE-(3*(LEVEL-1)))
  dt FROM dual 
CONNECT BY LEVEL <10 span=""> 
dt 
---------- 
7/5/2011 
7/2/2011 
6/29/2011 
6/26/2011 
6/23/2011 
6/20/2011 
6/17/2011 
6/14/2011 
6/11/2011 
 | 
 
To populate an empty
table with dummy varchar2 values, we can use DBMS_RANDOM.STRING
1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
13 
 | 
  
select DBMS_RANDOM.STRING('A',5)
  ran from dual connect
  by level<
  10; 
ran 
--------- 
zodaY 
baktb 
EUvWO 
WAcca 
rdRuw 
brQiw 
kcksX 
ddhmo 
EyoQl 
 | 
 
****************************************************
5. If you want to fill an
empty table with groups of data to work on analytic functions or group by
functions, then you can generate “groups” of numbers by manipulating the ROWNUM
column using the following query.
1 
2 
3 
4 
5 
6 
 | 
  
SQL> SELECT ROWNUM
  r, ROWNUM/2-0.1 a, trunc(ROWNUM/2-0.1) two, 
 2  ROWNUM/3-0.1
  b, trunc(ROWNUM/3-0.1) three, 
 3 
  ROWNUM/4-0.1 c, trunc(ROWNUM/4-0.1) four 
 4  
  FROM dual 
 5 
  CONNECT BY LEVEL <=20 
 6  ; 
 | 
 
The output [see the
columns marked TWO THREE and FOUR]:
1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
13 
14 
15 
16 
17 
18 
19 
20 
21 
22 
23 
24 
 | 
  
         R         
  A       
  TWO         
  B      THREE         
  C       FOUR 
----------
  ---------- ---------- ---------- ---------- ---------- ---------- 
         1       
  0.4          0
  0.23333333         
  0      
  0.15          0 
         2       
  0.9          0
  0.56666666         
  0       
  0.4          0 
         3       
  1.4         
  1       
  0.9         
  0      
  0.65          0 
         4       
  1.9          1
  1.23333333         
  1       
  0.9          0 
         5       
  2.4          2
  1.56666666          1      
  1.15          1 
         6       
  2.9         
  2       
  1.9         
  1       
  1.4          1 
         7       
  3.4          3
  2.23333333         
  2      
  1.65          1 
         8       
  3.9          3
  2.56666666         
  2       
  1.9          1 
         9       
  4.4         
  4       
  2.9          2      
  2.15          2 
        10       
  4.9          4
  3.23333333         
  3       
  2.4          2 
        11       
  5.4          5
  3.56666666         
  3      
  2.65          2 
        12       
  5.9         
  5       
  3.9         
  3       
  2.9          2 
        13       
  6.4          6
  4.23333333         
  4      
  3.15          3 
        14       
  6.9          6
  4.56666666         
  4       
  3.4          3 
        15       
  7.4         
  7       
  4.9          4      
  3.65          3 
        16       
  7.9          7
  5.23333333         
  5       
  3.9          3 
        17       
  8.4          8
  5.56666666         
  5      
  4.15          4 
        18       
  8.9         
  8       
  5.9          5       
  4.4          4 
        19       
  9.4          9
  6.23333333         
  6       4.65         
  4 
        20       
  9.9          9
  6.56666666         
  6       
  4.9          4 
20 rows selected 
 | 
 
****************************************************
6.
In this query, we need to update col2 in to_update table with the value in col4
of update_using table. If the value in col4 is already present in col2, then
col2 should not be updated. In this case since 11 is already present in
to_update table, it should not be updated for 1 in to_update table.
See
the output to get a better understanding of the requirement.
1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
 | 
  
CREATE TABLE to_update(col1
  NUMBER,col2 NUMBER); 
CREATE TABLE update_using(col3
  NUMBER,col4 NUMBER); 
INSERT INTO to_update
  VALUES(1,NULL); 
INSERT INTO to_update
  VALUES(2,NULL); 
INSERT INTO to_update
  VALUES(3,NULL); 
INSERT INTO to_update
  VALUES(4,11); 
INSERT INTO to_update
  VALUES(5,NULL); 
INSERT INTO to_update
  VALUES(6,NULL); 
INSERT INTO update_using
  VALUES(1,11); 
INSERT INTO update_using
  VALUES(2,12); 
INSERT INTO update_using
  VALUES(5,13); 
COMMIT; 
 | 
 
First solution using correlated subquery :
1 
2 
3 
4 
 | 
  
UPDATE to_update
  t SET t.col2=(SELECT
  col4 FROM update_using 
WHERE t.col1=col3 
  AND col4 NOT IN 
(SELECT col2
  FROM to_update WHERE
  col2 IS NOT NULL)) 
WHERE col2
  IS NULL 
 | 
 
But the above query will
fail if you add another row :
1 
 | 
  
INSERT INTO update_using
  VALUES(2,13); 
 | 
 
as it will not know
which value of col4 should be used to update col2. Here 2 has two corresponding
values 12 and 13.
The next solution uses
the concept of “update join” which introduces us to the concept of “key preserved table”. I will not get into the details.
The query given below will not work. For this to work, we need to have a
primary key on the table from which we are updating(update_using).
1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
 | 
  
SQL>
  update(SELECT a.col1,a.col2,b.col3,b.col4 FROM to_update
  a,update_using b 
  2 
  WHERE a.col1 =b.col3 ) 
  3 
  SET col2 =col4 
  4 
  WHERE col4 NOT IN
  (SELECT col2
  FROM to_update WHERE
  col2 IS NOT NULL) 
  5 
  ; 
update(SELECT a.col1,a.col2,b.col3,b.col4
  FROM to_update a,update_using b 
WHERE a.col1
  =b.col3 ) 
SET col2
  =col4 
WHERE col4
  NOT IN (SELECT col2 FROM to_update
  WHERE col2 IS NOT
  NULL) 
ORA-01779: cannot
  modify a column which maps to a
  non key-preserved table 
 | 
 
To make this query work,
create a primary key on update_using :
1 
2 
 | 
  
ALTER TABLE update_using 
ADD CONSTRAINT up_us_pk
  PRIMARY KEY(col3) 
 | 
 
Now when we run the
query :
1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
13 
14 
15 
16 
17 
18 
19 
20 
21 
22 
 | 
  
SQL>
  update(SELECT a.col1,a.col2,b.col3,b.col4 FROM to_update
  a,update_using b 
  2 
  WHERE a.col1 =b.col3 ) 
  3 
  SET col2 =col4 
  4 
  WHERE col4 NOT IN
  (SELECT col2
  FROM to_update WHERE
  col2 IS NOT NULL); 
2 rows updated 
SQL> select *
  from to_update 
  2 
  ; 
COL1 COL2 
---- ---- 
   1 
   2  
  12 
   3 
   4  
  11 
   5  
  13 
   6  
6 rows selected 
SQL> 
 | 
 
****************************************************
7. From a table
containing numbers, display only the digits after the decimal point. If a
number is 1.980 then the output should be 0.980
1 
2 
3 
4 
5 
6 
7 
 | 
  
CREATE TABLE test_decimal(num
  NUMBER); 
INSERT INTO test_decimal
  VALUES(1.2345); 
INSERT INTO test_decimal
  VALUES(20.0990); 
INSERT INTO test_decimal
  VALUES(1.00); 
INSERT INTO test_decimal
  VALUES(1.12357); 
INSERT INTO test_decimal
  VALUES(100); 
COMMIT; 
 | 
 
The table contains :
1 
2 
3 
4 
5 
6 
7 
 | 
  
NUM 
--------- 
1.2345 
20.099 
1 
1.12357 
100 
 | 
 
Answer:
1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
13 
14 
15 
16 
17 
18 
19 
20 
21 
 | 
  
SQL> select trunc(num)
  from test_decimal; 
TRUNC(NUM) 
---------- 
         1 
        20 
         1 
         1 
       100 
SQL> select num-trunc(num)
  from test_decimal; 
NUM-TRUNC(NUM) 
-------------- 
        0.2345 
         0.099 
             0 
       0.12357 
             0 
SQL> 
 | 
 
Alternative solutions:
1 
2 
 | 
  
select mod(num,1)
  from test_decimal; 
select num-cast(num
  as integer) from
  test_decimal; 
 | 
 
****************************************************
8. A table contains team
name and result. The result can have 3 values- WIN, LOSS or DRAW. For each team
find the total number of matches, number of wins, number of losses and the
number of drawn matches.
1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
 | 
  
CREATE TABLE match(team
  VARCHAR2(5),result VARCHAR2(4)); 
INSERT INTO match
  VALUES('A','WIN'); 
INSERT INTO match
  VALUES('A','LOSS'); 
INSERT INTO match
  VALUES('A','WIN'); 
INSERT INTO match
  VALUES('B','WIN'); 
INSERT INTO match
  VALUES('B','LOSS'); 
INSERT INTO match
  VALUES('C','WIN'); 
INSERT INTO match
  VALUES('C','DRAW'); 
INSERT INTO match
  VALUES('D','LOSS'); 
INSERT INTO match
  VALUES('E','DRAW'); 
COMMIT; 
 | 
 
1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
13 
14 
15 
 | 
  
SQL> select *
  from match; 
TEAM  RESULT 
----- ------ 
A    
  WIN 
A    
  LOSS 
A    
  WIN 
B    
  WIN 
B    
  LOSS 
C    
  WIN 
D    
  LOSS 
E    
  DRAW 
C    
  DRAW 
9 rows selected 
 | 
 
Answer :
1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
13 
14 
15 
16 
17 
18 
19 
 | 
  
SQL>  
-------------------- 
SQL>  SELECT team,win,lost,draw,win+lost+draw
  total FROM 
  2    
  (SELECT team,SUM(CASE
  WHEN result
  ='WIN' THEN 1 ELSE 0 END) win, 
  3    
  SUM(CASE WHEN result ='LOSS'
  THEN 1
  ELSE 0 END) lost, 
  4       
  SUM(CASE WHEN result ='DRAW'
  THEN 1
  ELSE 0 END) draw FROM
  match 
  5    
  GROUP BY team) 
  6 
  ; 
TEAM        
  WIN      
  LOST       DRAW     
  TOTAL 
----- ----------
  ---------- ---------- ---------- 
A             
  2         
  1         
  0          3 
B             
  1         
  1         
  0          2 
C             
  1         
  0         
  1          2 
D             
  0         
  1         
  0          1 
E             
  0         
  0         
  1          1 
SQL> 
 | 
 
****************************************************
9. A question similar to
the one solved above. In this case the table contains three columns. The first
column has the name of the first team, the second column has the name of the
second team and the third column contains the winner of the match. If the match
is a drawn match, then a ‘-’ is inserted into the winners column.
We need to write a query to find the total number of matches
played by each team, the number of drawn matches, the number of losses and
wins.
1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
 | 
  
CREATE TABLE vs(team1
  VARCHAR2(2),team2 VARCHAR2(2), winner VARCHAR2(2)); 
INSERT INTO vs
  VALUES('A','B','A'); 
INSERT INTO vs
  VALUES('A','B','B'); 
INSERT INTO vs
  VALUES('A','C','C'); 
INSERT INTO vs
  VALUES('A','D','A'); 
INSERT INTO vs
  VALUES('B','C','B'); 
INSERT INTO vs
  VALUES('B','D','B'); 
INSERT INTO vs
  VALUES('C','D','D'); 
INSERT INTO vs
  VALUES('A','D','-'); 
INSERT INTO vs
  VALUES('A','D','-'); 
COMMIT; 
 | 
 
Our Table :
1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
13 
14 
15 
16 
17 
 | 
  
SQL> select *
  from vs; 
TEAM1 TEAM2 WINNER 
----- ----- ------ 
A    
  B     A 
A    
  C     C 
A    
  D     A 
B    
  C     B 
B    
  D     B 
C    
  D     C 
A    
  B     B 
A    
  C     - 
A    
  D     - 
9 rows selected 
SQL> 
 | 
 
Answer :
1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
13 
14 
15 
16 
17 
18 
19 
20 
21 
 | 
  
SQL> select Team,sum(WIN)
  Win,sum(c)-sum(WIN)-sum(DRAW) Loss ,sum(DRAW) Draw,sum(c) TOTAL from ( 
  2 
  select team1 Team , 
  3 
  sum(case when team1=winner then
  1 else  0
  end) WIN, 
  4 
  sum(case when winner like
  '-' then 1
  else 0 end) DRAW, 
  5 
  count(team1) c from vs group by
  team1 
  6 
  union all 
  7 
  select team2 Team , 
  8 
  sum(case when team2=winner then
  1 else  0
  end) WIN, 
  9 
  sum(case when winner like
  '-' then 1
  else 0 end) DRAW, 
 10 
  count(team2) c from vs group by
  team2) 
 11  group by Team 
 12  ; 
TEAM       
  WIN      
  LOSS       DRAW     
  TOTAL 
---- ----------
  ---------- ---------- ---------- 
A            
  2         
  2          2         
  6 
B            
  3         
  1         
  0          4 
C            
  2         
  1         
  1          4 
D            
  0         
  3         
  1          4 
SQL> 
 | 
 
****************************************************
10. There are two tables-
‘has_sequence’ which contains a list of numbers and table ‘sequence_range’
which contains the start number and end number for each range. Write a query to
find those numbers from ‘has_sequence’ table which does not fall in any of the
range specified in the ‘sequence_range’ table.
1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
13 
14 
15 
16 
17 
18 
19 
20 
21 
22 
 | 
  
CREATE TABLE has_sequence
  (seq NUMBER); 
INSERT INTO has_sequence
  VALUES (3); 
INSERT INTO has_sequence
  VALUES (4); 
INSERT INTO has_sequence
  VALUES (5); 
INSERT INTO has_sequence
  VALUES (6); 
INSERT INTO has_sequence
  VALUES (7); 
INSERT INTO has_sequence
  VALUES (20); 
INSERT INTO has_sequence
  VALUES (21); 
INSERT INTO has_sequence
  VALUES (22); 
INSERT INTO has_sequence
  VALUES (23); 
INSERT INTO has_sequence
  VALUES (24); 
INSERT INTO has_sequence
  VALUES (31); 
INSERT INTO has_sequence
  VALUES (32); 
INSERT INTO has_sequence
  VALUES (33); 
INSERT INTO has_sequence
  VALUES (34); 
INSERT INTO has_sequence
  VALUES (35); 
INSERT INTO has_sequence
  VALUES (36); 
CREATE TABLE sequence_range(start_num
  NUMBER, end_num NUMBER); 
INSERT INTO sequence_range
  VALUES (4,6); 
INSERT INTO sequence_range
  VALUES (20,23); 
INSERT INTO sequence_range
  VALUES (30,34); 
COMMIT; 
 | 
 
The tables:
1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
13 
14 
15 
16 
17 
18 
19 
20 
21 
22 
23 
24 
25 
26 
27 
28 
29 
30 
31 
32 
 | 
  
SQL> SELECT *
  FROM has_sequence; 
SEQ 
--- 
  3 
  4 
  5 
  6 
  7 
 20 
 21 
 22 
 23 
 24 
 31 
 32 
 33 
 34 
 35 
 36 
16 rows selected 
SQL> SELECT *
  FROM sequence_range; 
START_NUM END_NUM 
--------- ------- 
        4      
  6 
       20     
  23 
       30     
  34 
SQL> 
 | 
 
We can see that the numbers 3,7,24,35 and 36 does not fall under
any of the ranges in ‘sequence_range’ table.
Answer:
1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
13 
14 
 | 
  
SQL> SELECT *
  FROM has_sequence h 
  2 
  WHERE   NOT
  EXISTS 
  3 
  (SELECT 1 FROM sequence_range s WHERE h.seq
  BETWEEN s.start_num AND
  s.end_num) 
  4 
  ; 
SEQ 
--- 
  3 
  7 
 24 
 35 
 36 
SQL> 
 | 
 
****************************************************
11. Another variation of
the above question is to update the ‘group_id’ field in ‘has_sequence’ field
with the ‘group_id’ field from ‘sequence_range’ table by matching the number
from ‘has_sequence’ and the corresponding sequence it belongs to, in the
‘sequence_range’ table.
1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
13 
14 
15 
16 
17 
18 
19 
20 
21 
22 
23 
24 
25 
26 
27 
28 
29 
30 
 | 
  
SQL> SELECT *
  FROM has_sequence; 
SEQ GROUPID 
--- ------- 
  3 
  4 
  5 
  6 
  7 
 20 
 21 
 22 
 23 
 24 
 31 
 32 
 33 
 34 
 35 
 36  
16 rows selected 
SQL> SELECT *
  FROM sequence_range ; 
START_NUM END_NUM
  GROUPID 
--------- -------
  ------- 
        4      
  6 A 
       20     
  23 B 
       30     
  34 C 
 | 
 
Answer :
1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
13 
14 
15 
16 
17 
18 
19 
20 
21 
22 
23 
24 
25 
26 
27 
28 
29 
 | 
  
SQL> UPDATE has_sequence
  t SET t.groupid = (SELECT
  s.groupid FROM  sequence_range
  s 
  2 
  WHERE t.seq BETWEEN
  s.start_num AND s.end_num); 
16 rows updated 
SQL> SELECT *
  FROM has_sequence; 
SEQ GROUPID 
--- ------- 
  3 
  4 A 
  5 A 
  6 A 
  7 
 20 B 
 21 B 
 22 B 
 23 B 
 24 
 31 C 
 32 C 
 33 C 
 34 C 
 35 
 36  
16 rows selected 
SQL> 
 | 
 
****************************************************
12. Useful in removing
multiple commas or spaces from a text.
Answer
1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
13 
14 
15 
16 
17 
18 
19 
20 
21 
 | 
  
SQL> 
SQL> SELECT 'how,,,to,,replace,,,,multiple,,,commas' FROM dual;
   
'HOW,,,TO,,REPLACE,,,,MULTIPLE 
-------------------------------------- 
how,,,to,,replace,,,,multiple,,,commas
   
SQL> SELECT
  replace(replace(REPLACE('how,,,to,,replace,,,,multiple,,,commas',',',' @'),'@
  ',''),' @',', ') 
FROM dual;  
REPLACE(REPLACE(REPLACE('HOW,, 
---------------------------------- 
how, to, replace,
  multiple, commas  
SQL> SELECT replace(replace(REPLACE('how,,,to,,replace,,,,multiple,,,commas',',','
  @'),'@ ',''),' @',' ') FROM dual;  
REPLACE(REPLACE(REPLACE('HOW,, 
------------------------------ 
how to replace multiple
  commas  
SQL> 
 | 
 
****************************************************
13. 1. Write a query to
find the date on which the first ‘FRIDAY’ of a month falls.
2. Write a query to find the date on which the last ‘FRIDAY’ of
a month falls.
3. Write a query to find the date on which the second ‘FRIDAY’
of a month falls.
Answer :
First ‘FRIDAY’ of the month:
1 
2 
 | 
  
SELECT next_day(trunc(SYSDATE,'MM')-1,'FRIDAY') 
first_of_month FROM dual; 
 | 
 
The ‘-1′ is required as the first ‘FRIDAY’ might fall on the 1st
of the month.
For eg. if 1-JULY-2011 falls on a FRIDAY, then without the ‘-1′ we
would get the next Friday, 8-JULY-2011.
Last ‘FRIDAY’ of the month:
1 
2 
 | 
  
SELECT next_day(last_day(trunc(SYSDATE))-7,'FRIDAY') 
last_of_month FROM dual 
 | 
 
Second ‘FRIDAY’ of the month:
1 
 | 
  
SELECT next_day((trunc(SYSDATE,'mm')-1)+7,'FRIDAY')
  FROM dual 
 | 
 
****************************************************
14. Some more queries on
dates.
1. Query to find the dates of all the ‘FRIDAY’ (or any other day
of the week) of a month.
1 
2 
3 
4 
5 
6 
7 
 | 
  
SELECT d
  FROM 
(SELECT  decode(trim(to_char(trunc(SYSDATE,'MM')-1+LEVEL,'DAY')), 
'FRIDAY',trunc(SYSDATE,'MM')-1+LEVEL)
  d 
FROM dual 
CONNECT BY LEVEL 
<=
  last_day(trunc(SYSDATE))+1-trunc(SYSDATE,'MM')-1) 
WHERE d
  IS NOT NULL 
 | 
 
This returns all the
dates which falls on a ‘FRIDAY’ for the current month.
2. Query to check if a given year is leap year:
There are two easy ways
to check if a year is a leap year or not.
In the first query,
using trunc with the format
mask ‘YYYY’ we go to the first day
of the year (1st Jan) and then add ’59′ days to it. If the year is a leap year,
then the 59th day will be the 29th of Feb. If it is not a leap year, then the
59th day will be the 1st of March. We check this by extracting the Month using
(MON). If MON returns ‘FEB’ then it is a leap year (TRUE) else it is not a leap
year.
1 
2 
3 
 | 
  
SELECT DECODE(TO_CHAR 
(TRUNC(TO_DATE('3/3/2004','DD/MM/YYYY'),'YYYY')+59, 
'MON'),'FEB','TRUE','FALSE')
  leap_year FROM dual 
 | 
 
In the second query, we
go to the last day of the year (31st dec).
In a leap year, the 31st of Dec is the 366th day of the year. We check if the
31st of Dec is the 366th day (for a leap year) or the 365th day ( for non leap
years).
1 
2 
3 
 | 
  
SELECT DECODE(TO_CHAR 
(TO_DATE('31/12/'||'2011','DD/MM/YYYY'),'DDD'), 
 '366','TRUE',
  'FALSE') leap_year FROM dual 
 | 
 
****************************************************