You are on page 1of 53

1) Transpose: Converting Rows to Columns

CREATE TABLE po_table (


po_num NUMBER,
terms_type NUMBER,
terms_description VARCHAR2(20)
);

INSERT INTO po_table VALUES(10, 1, 'Desc-10-1');


INSERT INTO po_table VALUES(10, 2, 'Desc-10-2');
INSERT INTO po_table VALUES(10, 3, 'Desc-10-3');
INSERT INTO po_table VALUES(20, 1, 'Desc-20-1');
INSERT INTO po_table VALUES(20, 3, 'Desc-20-3');
INSERT INTO po_table VALUES(30, NULL, NULL);

COMMIT;

Solution:
SELECT
po_num,
MAX(DECODE(terms_type, 1, terms_type)) AS terms1,
MAX(DECODE(terms_type, 1, terms_description)) AS terms1Desc,
MAX(DECODE(terms_type, 2, terms_type)) AS terms2,
MAX(DECODE(terms_type, 2, terms_description)) AS terms2Desc,
MAX(DECODE(terms_type, 3, terms_type)) AS terms3,
MAX(DECODE(terms_type, 3, terms_description)) AS terms3Desc
FROM
po_table
GROUP BY po_num
ORDER BY po_num;

(OR)

--PIVOTING QUERY

SELECT *
FROM
(SELECT deptno,job FROM emp GROUP BY deptno,job
) pivot (COUNT(*) FOR job IN
('MANAGER','CLERK','SALESMAN','ANALYST',NULL));

SELECT*
FROM(SELECT Size, ColorName, Qnty
FROM YourTable)p
PIVOT(SUM(Qnty)FOR Size IN([34],[32],[30])Pvt;

SELECT ColorName,
MAX(CASEWHEN Size =34THEN Qnty END)AS[34],
MAX(CASEWHEN Size =32THEN Qnty END)AS[32],
MAX(CASEWHEN Size =30THEN Qnty END)AS[30]
FROM Table1
GROUPBY ColorName;
2) EVEN AND ODD RECORDS:

EVEN RECORDS QUERY:

SELECT * FROM (SELECT EMP.*, ROWNUM FROM EMP) WHERE MOD (ROWNUM, 2) =0
OR
select * from (select eno,ename,sal, row_number() over(order by sal) ro from temp1) where
mod(ro,2)=0
(OR)
select * from emp where (rowid,0) in (select rowid,mod(rownum,2) from emp);
(OR)
select * from emp where rowid in (select decode(mod(rownum,2),0,rowid,null)
from emp);

ODD RECORDS QUERY:

SELECT * FROM (SELECT EMP.*, ROWNUM FROM EMP) WHERE MOD (ROWNUM, 2) =1
OR
select * from (select eno,ename,sal, row_number() over(order by sal) ro from temp1) where
mod(ro,2)=1
(OR)
select * from emp where (rowid,1) in (select rowid,mod(rownum,2) from emp);
(OR)
select * from emp where rowid in (select decode(mod(rownum,2),0,null,rowid)
from emp);

LISTAGG Function:

SELECT deptno, wm_concat(ename) AS employee


FROM emp
GROUP BY deptno;

(OR)
SELECT deptno, LISTAGG(ename,',') WITHIN GROUP (ORDER BY ename) AS employees
FROM emp
GROUP BY deptno;
(OR)

SELECT deptno ,
MAX(SYS_CONNECT_BY_PATH ( enamE, ',')) EMP_STRING
FROM
(SELECT empno , ename, deptno,
row_number() OVER ( PARTITION BY deptno ORDER BY rownum) rn
FROM EMP )
CONNECT BY deptno = PRIOR deptno
AND rn = PRIOR rn+1
START WITH rn =1
GROUP BY deptno
ORDER BY deptno;
DISPLAY DEPTNAME WHICH HAVE ONLY 3 EMPLOYEES:

select dname from dept where deptno in (select deptno from emp group by deptno having count(*)=3)

How to remove the special characters in Expression

select translate('ve*n%kat','[a-z]*%','[a-z]') from dual;

How to remove spaces in the expression ?

select translate(ename,' ','null') as ename from sample;

How to display all negative values in one column and positive


values in another column?

select case when sal>0 then sal end as possitive, case when
sal<0 then sal end as negative from sample;

HoW TO JOIN 3 OR MORE TABLES IN SINGLE QUERY:


SELECT p.Name, v.Name
FROM Production.Product p
JOIN Purchasing.ProductVendor pv
ON p.ProductID = pv.ProductID
JOIN Purchasing.Vendor v
ON pv.BusinessEntityID = v.BusinessEntityID
WHERE ProductSubcategoryID = 15
ORDER BY v.Name;
(OR)

SELECT lastname, firstname, tag, open_weekends


FROM drivers, vehicles, locations
WHERE drivers.location = vehicles.location
AND vehicles.location = locations.location
AND locations.open_weekends = 'Yes'

HOW TO DELETE DUPLICATE RECORDS BY USING dense_rank()


FUNCTION:
delete from emp where rowid in
(
select rid from
(
select rowid rid,
dense_rank() over(partition by empno order by rowid) rn
from emp
)
where rn > 1
);

How to display first ‘N’ Records from the table:

Select emp.*, rownum from emp where rownum<=10;

How to display LAST ‘N’ Records from table:

Select emp.*, rownum from emp

Minus

Select emp.*, rownum from emp where rownum<=(select max(rownum) – 5 from emp);

How to display 5th rec to 10th rec from table:

Select * from emp where rownum<=10

Minus

Select * from emp where rownum<=5;

(or)

Select * from emp where rownum between 5 and 10;

How to display ‘N th ‘ record from the table:

Select * from emp where rowed in (select max(rowed) from emp where rownum<=5);

To display top 5 highest salaries from the table based on salary :

Select * from (select emp.* from emp order by sal desc) where rownum<=5;

(or)

Select * from emp a where 5>=(select count(distinct(sal)) from emp b where a.sal<=b.sal);

To display top 5 least salaries from the table based on salary :

Select * from (select emp.* from emp order by sal ) where rownum<=5;
(or)
Select * from emp a where 5>=(select count(distinct(sal)) from emp b where a.sal>=b.sal);

To display Nth maximum Salary from the table:

Select * from emp a where 2=(select count(distinct(sal)) from emp b where a.sal<=b.sal);

(or)

Select * fromempwhere sal in(select sal from(select * fromemporderby sal


desc)whererownum<=5)
minus
Select * fromempwhere sal in(select sal from(select * fromemporderby sal
desc)whererownum<=4);

How to display count of NULL Values:

Select count(*) from emp where comm is null;

HOW TO DISPLAY COUNT OF EMPLOYEES WORKING IN EACH LOCATION:

selectCOUNT(*),b.loc from emp_b a innerjoin dept_b b on


(a.deptno=b.deptno)groupby b.loc;

HOW TO DISPLAY NAMES OF EMPLOYEE WHO GETTING SAME SALARIES:

SELECT ENAME, SAL FROM EMP WHERE SAL IN(SELECT SAL FROM EMP GROUPBY SAL
HAVINGCOUNT(*)>1);

SCD TYPE 2:
SELECT CNO, EFFECTIVEDATE, ENDDATE, NEXT_REC_EFFECTIVE_DATE,
DECODE (NEXT_REC_EFFECTIVE_DATE, NULL, ‘VALID’, ENDDATE,’VALID’,’INVALID’)
RECORD_STATUS FROM (SELECT CNO,EFFECTIVEDATE, ENDDATE,
LEAD (EFFECTIVEDATE, 1) OVER (PARTITION BY CNO ORDER BY
EFFECTIVEDATE)NEXT_REC_EFFECTIVE_DATE FROM CUST

3) DEPARTMENT WISE 2ND HIGHEST SALARY:


SELECT * FROM (SELECT ENO, ENAME, SAL, DEPT, DENSE_RANK() OVER (PARTITION BY
DEPT ORDER BY SAL) TEMP FROM TEMP1) WHERE TEMP =2

(OR)

select * from emp a where &n=(select count(distinct(sal)) from emp b where


a.deptno=b.deptno
and a.sal<=b.sal);

4) SECOND HIGHEST SALARY:


SELECT MAX (SAL) FROM EMP WHERE SAL< (SELECT MAX (SAL) FROM EMP)

5) SUM OF ONLY POSITIVE VALUES AND SUM OF ONLY NEGATIVE VALUES:

SELECT SUM (CASE WHEN


POSITIVE>0 THEN POSITIVE
ELSE 0
END) SUM OF POSITIVE VALUES,
SUM (CASE WHEN
NEGATIVE<0 THEN NEGATIVE
ELSE 0
END) SUM OF NEGATIVE VALUES
FROM TABLE_NAME

6) How to fetch positive values and negative values record counts?

Select count(*), ‘POSITIVEVALUES’ from TABLE_NAME


Where COLUMN_NAME>=0
UNION ALL
Select count(*), ‘POSITIVEVALUES’ from TABLE_NAME
Where COLUMN_NAME<0

7). FETCHING ONLY ALPHABETS & NUMERICS FROM THE COLUMN:

SELECT COL1 FROM TABLE WHERE REGEXP_LIKE (COL1,’ [A-Z]’)

SELECT COL1 FROM TABLE WHERE REGEXP_LIKE (COL1,’ [0-9]’)


8) CUMULATIVE SALARY:
SELECT ENO, ENAME, DEPTNO, SAL, SUM (SAL) OVER (PARTITION BY DEPTNO ORDER BY
DEPTNO, ENO, ENAME) CUM_SAL FROM EMP

9) DUPLICATE RECORDS:

SELECT ENO, COUNT (*) FROM EMP GROUP BY ENO HAVING COUNT (*)>1

10) DELETE DUPLICATE RECORDS:

DELETE FROM EMP WHERE ROWID NOT IN (SELECT MAX (ROWID) FROM EMP GROUP BY ENO)

(OR)

DELETE EMP A WHERE ROWID!=(SELECT MAX(ROWID) FROM EMP B WHERE


A.EMPNO=B.EMPNO);
11) LEAD FUNCTION: ADDING ROWS TO THE COLUMN ITSELF:

SELECT EMPNO, ENAME, DEPTNO, SAL, LEAD (SAL, 1, 0) OVER (ORDER BY SAL) AS
SAL_NEXT,LEAD (SAL, 1, 0) OVER (ORDER BY SAL) AS SAL_DIFFER FROM EMP;

12) LAG FUNCTION: ROWS TO THE COLUMN ITSELF:

SELECT EMPNO, ENAME, DEPTNO, SAL, LAG (SAL, 2, 0) OVER (ORDER BY SAL) AS FROM
EMP;

DENSE RANK: Without skipping the ranks in the column

13) Find the highest salary holder in each department.

SELECT * FROM (SELECT EMPNO, SAL, DENSE_RANK () OVER (PARTITION BY DEPTNO


ORDER BY SAL DESC) AS SAL_RANK FROM EMP) WHERE SAL_RANK =1

14) Nth highest salary

SELECT * FROM (SELECT EMPNO, SAL, DENSE_RANK () OVER (ORDER BY SAL DESC) AS
RANK FROM EMP) WHERE RANK = 1
RANK FUNCTION: Skips the ranks in the column.

15) Find the highest salary holder in each department.

SELECT * FROM (SELECT EMPNO, SAL, RANK () OVER (PARTITION BY DEPTNO ORDER BY
SAL DESC) AS SAL_RANK FROM EMP) WHERE SAL_RANK =1

15.1) Find the MAX 3 salary holder in each department.

SELECT * FROM EMP A WHERE 3>=(SELECT COUNT(DISTINCT(SAL)) FROM EMP B WHERE


A.DEPTNO=B.DEPTNO
AND A.SAL<=B.SAL)

15.2) Find the MIN 3 salary holder in each department

SELECT * FROM EMP A WHERE 3>=(SELECT COUNT(DISTINCT(SAL)) FROM EMP B WHERE


A.DEPTNO=B.DEPTNO
AND A.SAL>=B.SAL)

8) Nth HIGHEST SALARY:

SELECT * FROM (SELECT EMPNO, SAL, ROW_NUMBER () OVER (ORDER BY SAL DESC)
SAL_RANK FROM EMP ORDER BY SAL DESC) WHERE SAL_RANK = N

9) SUBSTRING FUNCTION:

Say I have a table column that has results like:


ABC_blahblahblah
DEFGH_moreblahblahblah
IJKLMNOP_moremoremoremore

I would like to be able to write a query that selects this column from said table, but only returns
the substring up to the Underscore (_) character. For example:
ABC
DEFGH
IJKLMNOP

SELECT SUBSTR ('ABC_blahblahblah', 0, INSTR ('ABC_blahblahblah', '_')-1) AS


output FROM EMP;
WITH CLASS:

with t(n,x,l)as (

select 'krishna,,rama,hari,hanumanjunction' n, to_char(null) x,1 l from dual


union all

select
n, case when l=1 then substr(n,l,instr(n,',',l,1)-1)
when instr(n,',',l,1)>0 then substr(n,l,instr(n,',',l,1)-l)
else substr(n,l)
end x, case when instr(n,',',l,1)>0 then instr(n,',',l,1)+1
else -1 end l

from
t
where case when instr(n,',',l,1) >0 then 1
else 0 end = 0 or l >0)

select * from t;

18) Which group function ignores the NULL value

Sol:count()

19) Which group function does not ignore the NULL value

Sol:

20) How NULL value is treated in order by class (in ascending or desending order)

Sol:LOW

21) Select 100+200 from emp;

Sol: Display 300 for every record

22) selec 1+2 from dept;

Sol: Display 3 for every record


23) SELECT ‘CHANDRA’ from dept;

SOL: Display ‘CHANDRA’ for every record

Select ename,length(ename) from emp where 4=length(ename);

Where 4=4(CORECT)

Where 4=5;

24) Select ename,job,deptno,sal from emp where deptno=20 and job=’Analyst’ or sal<=1500:

o/p:
25) Select ename,job,deptno,sal from emp where deptno=20 and (job=’Analyst’ or sal<=1500):

O/P:

26) Select ename,job,deptno,sal from emp where (deptno=20 and job=’Analyst’ or sal<=1500):

O/P:

27) how to retriew only capital letters from ENAME.

SRC Target
EMPNO ENAME SAL EMPNO ENAME SAL
1 adbfGHTyu 300 1 GHT 300
2 chANDra 3000 2 AND 3000
3 Adert 200 3 A 200
4 werzTR 700 4 TR 700
5 opERWt 900 5 ERW 900
Sol: SELECT regexp_replace('VeNkaT','[^A-Z]') FROM DUAL;

Note: ^ means Nagation , other than A-Z whatever characters are there those are replaced by NULL.
select col1 from tab1 where regexp_like(col1, '[a-z]');
RegEXP_like means regular expression

NOTE: regexp_like function will return entire value when it satisfy any single character .

EX: SELECT 'VEnkat' FROM DUAL WHERE REGEXP_LIKE('VEnkat','[A-Z]');

select risk_id, regexp_substr(region,'^;'+,1,level) from risk connect by regexp_substr(region,'^;'+,1,level) is


notnull

28) Count Query

selectcasewhen(selectCOUNT(*)as a from PRODU_STG )-(selectCOUNT(*)as b from


MIC_TARGET)-(selectCOUNT(*)as c from MIC_TARGET_REJECT)=0 then'Count
Matched'else'Count Un Matched'end

OR

Select count(* ), ‘STG’ from PRODU_STG

Union all

Select count(*) from (select count(*) from MIC_TARGET union select count(*)
from MIC_TARGET_reject)a

29) Pivot query

SOURCE:

SELECT PRODUT, [1] AS FILIAL1, [2] AS FILIAL2, [3] AS FILIAL3, [4] AS FILIAL4, [5] AS FILIAL5, [6] AS
FILIAL6, [7] AS FILIAL7

FROM ( SELECT PRODUT, FILIAL , dense_RANK() OVER (PARTITION BY PRODUT ORDER BY


PRODUT,REGIONAL1) AS TempRank FROM PROFL_STG ) A

PIVOT (MAX (FILIAL) FOR TempRank IN ([1],[2],[3],[4],[5],[6],[7])) AS PVT


TARGET:

SELECT ITEM_NBR_DEL,FILAL_1,FILAL_2,FILAL_3,FILAL_4,FILAL_5,FILAL_6,FILAL_7 FROM MIC_TARGET

30)

SELECT
(CASE
WHEN DIMEMBVDA ISNULL
OR(
CAST(SUBSTRING((CAST(DIMEMBVDA ASCHAR)),1,3)ASDECIMAL)=0)
THEN 1
ELSE
(CAST
(SUBSTRING
((REPLICATE('0','9'-
LEN(CAST(DIMEMBVDA ASVARCHAR)))
+CAST(DIMEMBVDA ASVARCHAR)
),1,3)
ASDECIMAL))
END),CODPRODU
FROM PRODU_STG
EXCEPT
SELECTWHPK_LENGTH_QTY ,ITEM_NBR_DEL FROM MIC_TARGET

31) The below query will display the result set having the “_” in the names.

SRC Target
EMPNO ENAME SAL EMPNO ENAME SAL
1 CHANDRA_RAJU 300 1 CHANDRA_RAJU 300
2 RAJU 3000 3 MOHAN_RAJU 200
3 MOHAN_RAJU 200 4 SANDEEP_123 700
4 SANDEEP_123 700
5 SASI 900

Select EMPNAME From EMPLOYEE Where EMPNAME LIKE '%\_%'ESCAPE'\'

32)
SRC Target
EMPNO ENAME SAL EMPNO ENAME SAL
1 CHANDRA_RAJU 300 001 CHANDRA_RAJU 300
2 RAJU 3000 002 RAJU 3000
10 MOHAN_RAJU 200 010 MOHAN_RAJU 200
11 SANDEEP_123 700 011 SANDEEP_123 700
100 SASI 900 100 SASI 900

(REPLICATE('0','9'-LEN(CAST(EMPNO AS NUMBER))

Q)

Now a days in ETL Testing there are asking 2 common questions.

1. Transpose Rows to Columns (There are n number of ways to achieve this….PIVOT function… and
simple one I am giving here)

2. Joins Through Vendiagrams.

Test Data
Student ID Term Fee Amount
10 1 10000
10 2 20000
10 3 30000
10 4 40000
20 1 20000
20 2 20000
20 3 20000
20 4 40000

Expected
Student
ID Term1 Fee Amount Term1 Fee Amount Term1 Fee Amount Term1 Fee Amount
10 1 10000 2 20000 3 30000 4 40000
20 1 20000 2 20000 3 20000 4 40000

Query :

Select studentid,

MAX(Decode(Term, 1, 1)) as term1, MAX(Decode(Term, 1, Fee Amount)) as FeeAmount,

MAX(Decode(Term, 2, 2)) as term2, MAX(Decode(Term, 2, Fee Amount)) as FeeAmount,

MAX(Decode(Term, 3, 3)) as term3, MAX(Decode(Term, 3, Fee Amount)) as FeeAmount,

MAX(Decode(Term, 4, 4)) as term4, MAX(Decode(Term, 4, Fee Amount)) as FeeAmount

From student_TABLEgroup by Student ID.

SQL> select * from a;

COL1

----------

SQL> select * from b;

CAL1 COL2

---------- ----------

1 1
1 1

1 1

1 1

Left outer join:

SQL> select a.col1,b.col2 from a left outer join b on a.col1=b.cal1;

COL1 COL2

---------- ----------

1 1

1 1

1 1

1 1

1 1

1 1

1 1

1 1

1 1

1 1

1 1

COL1 COL2

---------- ----------

1 1
12 rows selected.

Router outer join:

SQL> select a.col1,b.col2 from a right outer join b on a.col1=b.cal1;

COL1 COL2

---------- ----------

1 1

1 1

1 1

1 1

1 1

1 1

1 1

1 1

1 1

1 1

1 1

COL1 COL2

---------- ----------

1 1
12 rows selected.

Full outer join:

SQL> select a.col1,b.col2 from a full outer join b on a.col1=b.cal1;

COL1 COL2

---------- ----------

1 1

1 1

1 1

1 1

1 1

1 1

1 1

1 1

1 1

1 1

1 1

COL1 COL2

---------- ----------

1 1

12 rows selected.
Please observe below Query:

SQL> select deptno, count(deptno) over (partition by deptno) as no from emp;

DEPTNO NO

---------- ----------

10 3

10 3

10 3

20 5

20 5

20 5

20 5

20 5

30 6

30 6

30 6

DEPTNO NO

---------- ----------

30 6

30 6

30 6
14 rows selected.

DUPLICATE CHECK

SQL> select sal,count(*) from emp group by sal having count(*)>1;

SAL COUNT(*)

---------- ----------

1250 2

3000 2

2.----------------------------------------------------------
33) Columns to Rows:

Consider this data table:


Select key, c1, c2, c3 from t order by key;

KEY C1 C2 C3
--- ----- ----- ---
r1 v1 v2 v3
r2 v1 v2
r3 v1 v3
r4 v1
r5 v2 v3
r6 v2
r7 v3
r8

We can convert each row of C1, C2, and C3 values into three rows of values
under a single column as follows. Break on key skip 1 duplicate

Select key, source, Val from t UNPIVOT INCLUDE NULLS (VAL FOR (SOURCE) IN
(C1 AS 'C1',C2 AS 'C2',C3 AS 'C3'))Order by key, source;

Types of Validations:

1) If source is a FF and target is DB then how you are going to validate the data.

Sol: By using open source tools like beyond comparator tool, etc

2) If there is no access to DB how your are going to validate the data.

Sol: By using Unix box we can compare two tables.

3) How you are going to validate the data by using DB

Sol: by using minus query.

4) If you are loading data from N number of source systems to single target. Then how your are
going to validate the data

Sol: In the source system we can do union for different sources as a subquey and it will pass results to
the parent query then you can perform validation against target table.

5) How you are going to check whether valid data is loaded into the target table.

Sol: select (case when ename is null then 0 else 1 end) as ename from emp
Minus
Select ename from emp_t

6) If you are having surrogate key in Table how you are going to validate?

Sol: Omit the surrogate key and perform the validation


ETL Performance Testing and Tuning
ETL performance testingis a confirmation test to ensure that an ETL system can handle the load
of multiple users and transactions. The goal of performance tuning is to optimize session
performance by eliminating performance bottlenecks. To tune or improve the performance of the
session, you have to identify performance bottlenecks and eliminate it. Performance bottlenecks
can be found in source and target databases, the mapping, the session and the system. One of
the best tools used for performance testing is Informatica.

Sol :

select dname from dept where deptno in (select deptno from emp group by deptno having count(*)>=3)

Q) what is the difference between COUNT(*) and COUNT(1) ? which one is the performance wise best?

Q) Difference between DECODE and CASE?

Q) If ELSE condition will not specified In CASE statement what will happen ?

Q) What is the difference between RANK and DENSE_RANK? tell me the example in which situation we
are use?

Q) What is the difference between IN, EXISTS, ANY, ALL, SOME operators ?

Q) Difference between CAST and CONVERT functions?

Q) Difference between Left outer join and Right outer join?

Q) Difference between DELETE, TRUNCATE and DROP ?


CONNECT BY LEVEL Query:

select id, level as lvl


from a
connectby level <=2
orderby id, level

(OR)

select id, lvl


from(select level as lvl
from dual
connectby level <=2
)
crossjoin a
orderby id, lvl

(OR)

select id, lvl


from(select level as lvl
from dual
connectby level <=2
)
crossjoin a
orderby id, lvl

(OR)

select lpad(' ',2*(level-1)) || to_char(child) s

from test_connect_by

start with parent is null

connect by prior child = parent;

(OR)

select

lpad(' ', 2*level) || child

from

prune_test

start with

parent is null

connect by

prior child=parent
and parent not in (1, 71);

Hierarchical Queries

DROP TABLE tab1 PURGE;

CREATE TABLE tab1 (


id NUMBER,
parent_id NUMBER,
CONSTRAINT tab1_pk PRIMARY KEY (id),
CONSTRAINT tab1_tab1_fk FOREIGN KEY (parent_id) REFERENCES tab1(id)
);

CREATE INDEX tab1_parent_id_idx ON tab1(parent_id);

INSERT INTO tab1 VALUES (1, NULL);


INSERT INTO tab1 VALUES (2, 1);
INSERT INTO tab1 VALUES (3, 2);
INSERT INTO tab1 VALUES (4, 2);
INSERT INTO tab1 VALUES (5, 4);
INSERT INTO tab1 VALUES (6, 4);
INSERT INTO tab1 VALUES (7, 1);
INSERT INTO tab1 VALUES (8, 7);
INSERT INTO tab1 VALUES (9, 1);
INSERT INTO tab1 VALUES (10, 9);
INSERT INTO tab1 VALUES (11, 10);
INSERT INTO tab1 VALUES (12, 9);
COMMIT;
Basic Hierarchical Query
In its simplest form a hierarchical query needs a definition of how each child relates to its parent.
This is defined using the CONNECT BY .. PRIOR clause, which defines how the current row (child)
relates to a prior row (parent). In addition, the START WITH clause can be used to define the
root node(s) of the hierarchy. Hierarchical queries come with operators, pseudocolumns and
functions to help make sense of the hierarchy.

 LEVEL : The position in the hierarchy of the current row in relation to the root node.
 CONNECT_BY_ROOT : Returns the root node(s) associated with the current row.
 SYS_CONNECT_BY_PATH : Returns a delimited breadcrumb from root to the current row.
 CONNECT_BY_ISLEAF : Indicates if the current row is a leaf node.
 ORDER SIBLINGS BY : Applies an order to siblings, without altering the basic hierarchical
structure of the data returned by the query.

The following query gives an example of these items based on the previously defined test table.

SET PAGESIZE 20 LINESIZE 110


COLUMN tree FORMAT A20
COLUMN path FORMAT A20

SELECT id,
parent_id,
RPAD('.', (level-1)*2, '.') || id AS tree,
level,
CONNECT_BY_ROOT id AS root_id,
LTRIM(SYS_CONNECT_BY_PATH(id, '-'), '-') AS path,
CONNECT_BY_ISLEAF AS leaf
FROM tab1
START WITH parent_id IS NULL
CONNECT BY parent_id = PRIOR id
ORDER SIBLINGS BY id;

ID PARENT_ID TREE LEVEL ROOT_ID PATH


LEAF
---------- ---------- -------------------- ---------- ---------- ----------------
---- ----------
1 1 1 1 1
0
2 1 ..2 2 1 1-2
0
3 2 ....3 3 1 1-2-3
1
4 2 ....4 3 1 1-2-4
0
5 4 ......5 4 1 1-2-4-5
1
6 4 ......6 4 1 1-2-4-6
1
7 1 ..7 2 1 1-7
0
8 7 ....8 3 1 1-7-8
1
9 1 ..9 2 1 1-9
0
10 9 ....10 3 1 1-9-10
0
11 10 ......11 4 1 1-9-10-11
1
12 9 ....12 3 1 1-9-12
1

Cyclic Hierarchical Query


It is possible for a hierarchy to be cyclical, which can represent a problem when querying the
data.

-- Create a cyclic reference


UPDATE tab1 SET parent_id = 9 WHERE id = 1;
COMMIT;

SELECT id,
parent_id,
RPAD('.', (level-1)*2, '.') || id AS tree,
level,
CONNECT_BY_ROOT id AS root_id,
LTRIM(SYS_CONNECT_BY_PATH(id, '-'), '-') AS path,
CONNECT_BY_ISLEAF AS leaf
FROM tab1
START WITH parent_id IS NULL
CONNECT BY parent_id = PRIOR id
ORDER SIBLINGS BY id;
ERROR:
ORA-01436: CONNECT BY loop in user data

To simplify matters, the CONNECT BY NOCYCLE clause tells the database not to traverse cyclical
hierarchies. In this case the CONNECT_BY_ISCYCLE function indicates which record is responsible
for the cycle.
We can now use the NOCYCLE option and check the results of the CONNECT_BY_ISCYCLE function.

SELECT id,
parent_id,
RPAD('.', (level-1)*2, '.') || id AS tree,
level,
CONNECT_BY_ROOT id AS root_id,
LTRIM(SYS_CONNECT_BY_PATH(id, '-'), '-') AS path,
CONNECT_BY_ISLEAF AS leaf,
CONNECT_BY_ISCYCLE AS cycle
FROM tab1
START WITH id = 1
CONNECT BY NOCYCLE parent_id = PRIOR id
ORDER SIBLINGS BY id;

ID PARENT_ID TREE LEVEL ROOT_ID PATH


LEAF CYCLE
---------- ---------- -------------------- ---------- ---------- ----------------
---- ---------- ----------
1 9 1 1 1 1
0 0
2 1 ..2 2 1 1-2
0 0
3 2 ....3 3 1 1-2-3
1 0
4 2 ....4 3 1 1-2-4
0 0
5 4 ......5 4 1 1-2-4-5
1 0
6 4 ......6 4 1 1-2-4-6
1 0
7 1 ..7 2 1 1-7
0 0
8 7 ....8 3 1 1-7-8
1 0
9 1 ..9 2 1 1-9
0 1
10 9 ....10 3 1 1-9-10
0 0
11 10 ......11 4 1 1-9-10-11
1 0
12 9 ....12 3 1 1-9-12
1 0

PIVOT
The PIVOT operator takes data in separate rows, aggregates it and converts it into columns. To
see the PIVOT operator in action we need to create a test table.

CREATE TABLE pivot_test (


id NUMBER,
customer_id NUMBER,
product_code VARCHAR2(5),
quantity NUMBER
);

INSERT INTO pivot_test VALUES (1, 1, 'A', 10);


INSERT INTO pivot_test VALUES (2, 1, 'B', 20);
INSERT INTO pivot_test VALUES (3, 1, 'C', 30);
INSERT INTO pivot_test VALUES (4, 2, 'A', 40);
INSERT INTO pivot_test VALUES (5, 2, 'C', 50);
INSERT INTO pivot_test VALUES (6, 3, 'A', 60);
INSERT INTO pivot_test VALUES (7, 3, 'B', 70);
INSERT INTO pivot_test VALUES (8, 3, 'C', 80);
INSERT INTO pivot_test VALUES (9, 3, 'D', 90);
INSERT INTO pivot_test VALUES (10, 4, 'A', 100);
COMMIT;

So our test data starts off looking like this.

SELECT * FROM pivot_test;

ID CUSTOMER_ID PRODU QUANTITY


---------- ----------- ----- ----------
1 1 A 10
2 1 B 20
3 1 C 30
4 2 A 40
5 2 C 50
6 3 A 60
7 3 B 70
8 3 C 80
9 3 D 90
10 4 A 100

10 rows selected.

SQL>

In its basic form the PIVOT operator is quite limited. We are forced to list the required values
to PIVOT using the IN clause.

SELECT *
FROM (SELECT product_code, quantity
FROM pivot_test)
PIVOT (SUM(quantity) AS sum_quantity FOR (product_code) IN ('A' AS a, 'B' AS b,
'C' AS c));

A_SUM_QUANTITY B_SUM_QUANTITY C_SUM_QUANTITY


-------------- -------------- --------------
210 90 160

1 row selected.

SQL>

If we want to break it down by customer, we simply include the CUSTOMER_ID column in the initial
select list.

SELECT *
FROM (SELECT customer_id, product_code, quantity
FROM pivot_test)
PIVOT (SUM(quantity) AS sum_quantity FOR (product_code) IN ('A' AS a, 'B' AS b,
'C' AS c))
ORDER BY customer_id;

CUSTOMER_ID A_SUM_QUANTITY B_SUM_QUANTITY C_SUM_QUANTITY


----------- -------------- -------------- --------------
1 10 20 30
2 40 50
3 60 70 80
4 100

4 rows selected.

SQL>

Prior to 11g we could accomplish a similar result using the DECODE function combined with
aggregate functions.

SELECT SUM(DECODE(product_code, 'A', quantity, 0)) AS a_sum_quantity,


SUM(DECODE(product_code, 'B', quantity, 0)) AS b_sum_quantity,
SUM(DECODE(product_code, 'C', quantity, 0)) AS c_sum_quantity
FROM pivot_test
ORDER BY customer_id;

A_SUM_QUANTITY B_SUM_QUANTITY C_SUM_QUANTITY


-------------- -------------- --------------
210 90 160

1 row selected.

SQL>

SELECT customer_id,
SUM(DECODE(product_code, 'A', quantity, 0)) AS a_sum_quantity,
SUM(DECODE(product_code, 'B', quantity, 0)) AS b_sum_quantity,
SUM(DECODE(product_code, 'C', quantity, 0)) AS c_sum_quantity
FROM pivot_test
GROUP BY customer_id
ORDER BY customer_id;

CUSTOMER_ID A_SUM_QUANTITY B_SUM_QUANTITY C_SUM_QUANTITY


----------- -------------- -------------- --------------
1 10 20 30
2 40 0 50
3 60 70 80
4 100 0 0

4 rows selected.

SQL>
UNPIVOT
The UNPIVOT operator converts column-based data into separate rows. To see
the UNPIVOT operator in action we need to create a test table.

CREATE TABLE unpivot_test (


id NUMBER,
customer_id NUMBER,
product_code_a NUMBER,
product_code_b NUMBER,
product_code_c NUMBER,
product_code_d NUMBER
);

INSERT INTO unpivot_test VALUES (1, 101, 10, 20, 30, NULL);
INSERT INTO unpivot_test VALUES (2, 102, 40, NULL, 50, NULL);
INSERT INTO unpivot_test VALUES (3, 103, 60, 70, 80, 90);
INSERT INTO unpivot_test VALUES (4, 104, 100, NULL, NULL, NULL);
COMMIT;

So our test data starts off looking like this.

SELECT * FROM unpivot_test;

ID CUSTOMER_ID PRODUCT_CODE_A PRODUCT_CODE_B PRODUCT_CODE_C


PRODUCT_CODE_D
---------- ----------- -------------- -------------- -------------- -------------
-
1 101 10 20 30
2 102 40 50
3 103 60 70 80
90
4 104 100

4 rows selected.
SQL>

The UNPIVOT operator converts this column-based data into individual rows.

SELECT *
FROM unpivot_test
UNPIVOT (quantity FOR product_code IN (product_code_a AS 'A', product_code_b AS
'B', product_code_c AS 'C', product_code_d AS 'D'));

ID CUSTOMER_ID P QUANTITY
---------- ----------- - ----------
1 101 A 10
1 101 B 20
1 101 C 30
2 102 A 40
2 102 C 50
3 103 A 60
3 103 B 70
3 103 C 80
3 103 D 90
4 104 A 100

10 rows selected.

SQL>

There are several things to note about the query:

 The required column names, in this case QUANTITY and PRODUCT_CODE, are define in
the UNPIVOT clause. These can be set to any name not currently in the driving table.
 The columns to be unpivoted must be named in the IN clause.
 The PRODUCT_CODE value will match the column name it is derived from, unless you alias
it to another value.
 By default the EXCLUDE NULLS clause is used. To override the default behaviour use
the INCLUDE NULLS clause.

The following query shows the inclusion of the INCLUDE NULLS clause.
SELECT *
FROM unpivot_test
UNPIVOT INCLUDE NULLS (quantity FOR product_code IN (product_code_a AS 'A',
product_code_b AS 'B', product_code_c AS 'C', product_code_d AS 'D'));

ID CUSTOMER_ID P QUANTITY
---------- ----------- - ----------
1 101 A 10
1 101 B 20
1 101 C 30
1 101 D
2 102 A 40
2 102 B
2 102 C 50
2 102 D
3 103 A 60
3 103 B 70
3 103 C 80

ID CUSTOMER_ID P QUANTITY
---------- ----------- - ----------
3 103 D 90
4 104 A 100
4 104 B
4 104 C
4 104 D

16 rows selected.

SQL>

Prior to 11g, we can get the same result using the DECODE function and a pivot table with the
correct number of rows. In the following example we use the CONNECT BY clause in a query
from dual to generate the correct number of rows for the unpivot operation
SELECT id,
customer_id,
DECODE(unpivot_row, 1, 'A',
2, 'B',
3, 'C',
4, 'D',
'N/A') AS product_code,
DECODE(unpivot_row, 1, product_code_a,
2, product_code_b,
3, product_code_c,
4, product_code_d,
'N/A') AS quantity
FROM unpivot_test,
(SELECT level AS unpivot_row FROM dual CONNECT BY level <= 4)
ORDER BY 1,2,3;

ID CUSTOMER_ID PRO QUANTITY


---------- ----------- --- ----------
1 101 A 10
1 101 B 20
1 101 C 30
1 101 D
2 102 A 40
2 102 B
2 102 C 50
2 102 D
3 103 A 60
3 103 B 70
3 103 C 80

ID CUSTOMER_ID PRO QUANTITY


---------- ----------- --- ----------
3 103 D 90
4 104 A 100
4 104 B
4 104 C
4 104 D

16 rows selected.

SQL>

Q) what is the difference between COUNT(*) and COUNT(1) ? which one is the performance wise best?

A) Count(*) will consider all the columns and rows as well whereas Count(1) will consider only one column and with all
rows..For example a column with named ‘1’ is appended with having values as 1 for all the available rows in that table.
Count(1) is the more performance than Count(*).

Q) Difference between DECODE and CASE?

A) NULL value can be literally used in Decode whereas not in the Case.And, Case is more performance than
Decode. Constants and expressions only allowed , relational operators not allowed in decode.

Q) What is the difference between RANK and DENSE_RANK? tell me the example in which situation we
are use?

A) Rank gives the ranks with gaps , but dense rank not… Wherever duplicates appeared the same rank would be
repeated for both..remaining values would be given the rank by skipping the next number to the repeated number

Q) What is the difference between IN, EXISTS, ANY, ALL, SOME operators ?

A) IN will hold the memory.. whereas exists wont.. Exists, any, all, some are useful when you are using correlated
quries. Q) Difference between Left outer join and Right outer join? Left outer join to get all the rows which are
matched with right table and not matched with right table. Right outer is to get the all the rows which are matched with
left table and not matched weith left table.

Q) Difference between Left outer join and Right outer join?

A) Left outer join to get all the rows which are matched with right table and not matched with right table. Right outer is to get
the all the rows which are matched with left table and not matched weith left table.

Q) What about the MERGE Statement ? Give an eample?

A) To put all the DML operations in one single statement. Based on the condition, corresponding DML operation (insert,
update, delete) would work.
1)

SOURCE:

DEPTNO NAME

10 A

10 B

20 C

20 D

TARGET:

DEPTNO NAME

10 A

10 A,B

20 A,B,C

20 A,B,C,D

A)

ANS:- Table T

SELECT x,

data,

SYS_CONNECT_BY_PATH(data, '/')

FROM

(SELECT x,data,rownum Parent, rownum-1 child FROM T

) t1

START WITH child =0


CONNECT BY prior parent=child;

Result:

2)

SOURCE:

ID NAME LOC START_DT END_DT

1001 A HYD 20/09/2016 25/09/2016

1002 B BAN 21/09/2016 23/09/2016

1003 C CHE 22/09/2016 25/09/2016

1002 B HYD 23/09/2016 NULL

1004 D BAN 24/09/2016 NULL

1001 A BAN 25/09/2016 NULL

1005 E CHE 25/09/2016 NULL

1003 C HYD 25/09/2016 NULL

QUESTION : Display the only last updated records from the above table?

A)

select

from test

start with enddt is null


connect by prior startdt = enddt and level < 2

3)

SOURCE:

ITEM NO_OF_TIMES

A 2

B 5

C 4

TARGET:

ITEM

A) with t1(d,cnt,l) as( select 'A' d, 2 cnt, 1 l from dual union all select d, cnt, l+1 l from t1 where l <=cnt) select * from t1
where l >1;

OR
with t1(d,cnt,l) as( select * from (select data, x, 1 l from T ) union all select d, cnt, l+1 l from t1 where l <=cnt) select * from t1
where l >1 order by d;

(OR)

ANS: Create the table T as mentioned above screen shot and the data in the table as below.

with t1(data,x,l) as(

select data , x , 1 l from T where x >0

union all

select data, x, l+1 l from t1 where l < x

select * from t1;

4)

SOURCE:

METERIAL COMPONANT

M1 M1C1

M1C1 M1C2
M1C2 C1

M2 C2

M1C2 C3

TARGET:

METERIAL COMPONANT

M1 C1

M1 C3

M2 C2

5)

SOURCE:

DEPTNO NAME

10 A

10 B

10 C

20 D

20 E

20 F

TARGET:

DEPTNO NAME

10 A

10 A,B

10 A,B,C

20 D

20 D,E
20 D,E,F

ANS: consider emp table as source

SELECT deptno,
SYS_CONNECT_BY_PATH(ename, '/')
FROM
(SELECT empno,
ename,
deptno,
row_number() over (partition BY deptno order by deptno) parent,
row_number() over (partition BY deptno order by deptno)-1 child
FROM emp
)e
START WITH parent =1
CONNECT BY prior parent=child
AND prior deptno =deptno;

6)

SOURCE:

DEPTNO NAME
10 A

10 B

10 C

20 D

20 E

20 F

TARGET:

DEPTNO NAME

10 A,B,C

20 D,E,F

ANS: EMP table as source.

SELECT deptno,
LISTAGG(ename, ',') WITHIN GROUP (
ORDER BY ename) AS employees
FROM emp
GROUP BY deptno;

7)

SOURCE:

COL1 COL2 COL3

A B C

D E F
TARGET:

COL

ANS : Table and table data as below

select col
fromtunpivot
unpivot
(

col for VALUE_TYPE in (VAL1,VAL2,VAL3)


);

8)

SOURCE:
ID VAL

10 A

10 B

20 E

20 D

10 C

20 F

TARGET:

ID VAL1 VAL2 VAL3

10 A B C

20 D E F

ANS : data as result of the inner query


Result is

9)
SOURCE:

NAME

TARGET 1:

TARGET 2:

A) SELECT y.name (SELECT name FROM emp ) y, (SELECT name FROM emp GROUP BY name HAVING COUNT(*) >1
) x WHERE y.name=x.name;

(or)
select name from emp e1 where (select count(*) from emp e2 where e1.name=e2.name) >1;

(OR)

ANS :

Table T has data as below 1 is duplicated, 2, 3 are not duplicated.

Tables Test123 as below

Need to send duplicate rows to one table T ,non duplicate rows into another table Test123

INSERT ALL
when c > 1 then
INTO Test123(x) values (x)
when c =1 then
INTO T(x) values (x)
with names as (
select x,(select count(*) from T e2 where e1.x=e2.x) c from T e1 where (select count(*) from T e2
where e1.x=e2.x) >1
union all
select x,(select count(*) from T e2 where e1.x=e2.x)c from T e1 where (select count(*) from T e2
where e1.x=e2.x) =1)
SELECT * FROM names;

Test123
T

10)

Q) Student Table :

Student Age Subject

Adam 15 Biology, Maths

Alex 14 Maths

Stuart 17 Maths
Student Age Subject

Adam 15 Biology

Adam 15 Maths

Alex 14 Maths

Stuart 17 Maths

Write a SQL Query to Display data as above table?

A)

with t1(x,n,r,l)as ( select x, data n, to_char(null) y,1 l from T union all select x, n, case when l=1 then
substr(n,l,instr(n,',',l,1)-1) when instr(n,',',l,1)>0 then substr(n,l,instr(n,',',l,1)-l) else substr(n,l) end y, case
when instr(n,',',l,1)>0 then instr(n,',',l,1)+1 else -1 end l from t1 where case when instr(n,',',l,1) >0 then 1
else 0 end = 0 or l >0) select * from t1 where l <>1 order by x;

(OR)

Table T data as below

WITH t1(x,n,r,l)AS
( SELECT x, data n, TO_CHAR(NULL) y,1 l FROM T WHERE instr(data,',',1,1) >0
UNION ALL
SELECT x,
n,
CASE
WHEN l=1
THEN SUBSTR(n,l,instr(n,',',l,1)-1)
WHEN instr(n,',',l,1)>0
THEN SUBSTR(n,l,instr(n,',',l,1)-l)
ELSE SUBSTR(n,l)
END y,
CASE
WHEN instr(n,',',l,1)>0
THEN instr(n,',',l,1)+1
ELSE -1
END l
FROM t1
WHERE
CASE
WHEN instr(n,',',l,1) >0
THEN 1
ELSE 0
END = 0
OR l >0
)
SELECT * FROM t1 WHERE l <>1 ORDER BY x;

Result

You might also like