0% found this document useful (0 votes)
6 views

Oracle_Functions_01

The document explains the differences between SQL ranking functions: RANK, DENSE_RANK, and ROW_NUMBER. RANK assigns ranks with gaps for duplicates, DENSE_RANK assigns consecutive ranks without gaps, and ROW_NUMBER assigns unique sequential numbers regardless of duplicates. Additionally, it discusses the use of PIVOT and UNPIVOT operators for transforming table data in SQL.

Uploaded by

stkumara
Copyright
© © All Rights Reserved
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
6 views

Oracle_Functions_01

The document explains the differences between SQL ranking functions: RANK, DENSE_RANK, and ROW_NUMBER. RANK assigns ranks with gaps for duplicates, DENSE_RANK assigns consecutive ranks without gaps, and ROW_NUMBER assigns unique sequential numbers regardless of duplicates. Additionally, it discusses the use of PIVOT and UNPIVOT operators for transforming table data in SQL.

Uploaded by

stkumara
Copyright
© © All Rights Reserved
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
You are on page 1/ 15

/

***********************************************************************************
**********************************/

What is the difference between RANK and DENSE_RANK and ROW_NUMBER?

The row_number gives continuous numbers, while rank and dense_rank give the same
rank for duplicates,
but the next number in rank is as per continuous order so you will see a jump but
in dense_rank doesn't
have any gap in rankings.

Compare RANK(), DENSE_RANK(), and ROW_NUMBER() function

RANK(), DENSE_RANK(), and ROW_NUMBER() function have very similar behaviors. Here
we put them together to visually and programmatically illustrate their common
attributes as well as differences.
RANK()
The RANK() function allocates a rank (integer number) to each row within a group of
a data set, with gaps, and the rank values could duplicate.

When a student has the same mark as another student, they both receive the same
rank value, but unlike DENSE_RANK() function, RANK() function does NOT assign
consecutive ranks.
In Class A, both Gary and Tom are assigned the same rank value 2 as they have the
same mark, but John receives rank value 4 where 3 is skipped.

SELECT StudentName,
ClassName,
StudentMark,
RANK() OVER (PARTITION BY ClassName ORDER BY StudentMark DESC) as StudentRank
FROM exam_result;

DENSE_RANK()
The DENSE_RANK() function allocates a rank (integer number) to each row within a
group of a data set, without gaps, and the rank values could duplicate.

When a student has the same mark as another student, they both receive the same
rank value, but unlike RANK() function, DENSE_RANK() function assigns consecutive
rank values.
In Class A, both Gary and Tom are assigned the same rank value 2 as they have the
same mark, and John receives rank value 3 which is consecutively incremented from
2.

SELECT StudentName,
ClassName,
StudentMark,
DENSE_RANK() OVER (PARTITION BY ClassName ORDER BY StudentMark DESC) as
StudentRank
FROM exam_result;

ROW_NUMBER()
The ROW_NUMBER() function allocates a different row number (integer number,
starting from 1) to each row within a group of a
data set, without both gaps and duplicated values.
When a student has the same mark as another student, each of them receives a
distinct row number. Furthermore,
unlike RANK() and DENSE_RANK(), ROW_NUMBER() function assigns consecutive, non-
duplicated numbers.

In Class A, both Gary and Tom are assigned different numbers even though they have
the same mark, and John receives number
4 which is consecutively incremented from 3.

SELECT StudentName,
ClassName,
StudentMark,
ROW_NUMBER() OVER (PARTITION BY ClassName ORDER BY StudentMark DESC) as
StudentRank
FROM exam_result;

Put all 3 functions together

In the following query, we put RANK(), DENSE_RANK(), and ROW_NUMBER() function into
a single query. Please note that we
have used each function's name as alias for column names, but because they are
reserved words in MySQL, we have to surround
(a.k.a. escape) them by double quotes (alternatively you can use back tick
character ` instead of double quotes).

SELECT StudentName,
ClassName,
StudentMark,
RANK() OVER (PARTITION BY ClassName ORDER BY StudentMark DESC) as "RANK",
DENSE_RANK() OVER (PARTITION BY ClassName ORDER BY StudentMark DESC) as
"DENSE_RANK",
ROW_NUMBER() OVER (PARTITION BY ClassName ORDER BY StudentMark DESC) as
"ROW_NUMBER"
FROM exam_result;

/
***********************************************************************************
**********************************/

Execute the following script to create a database called ShowRoom and containing a
table called Cars (that contains 15 random
records of cars):

CREATE Database ShowRoom;


GO
USE ShowRoom;

CREATE TABLE Cars


(
id INT,
name VARCHAR(50) NOT NULL,
company VARCHAR(50) NOT NULL,
power INT NOT NULL
)

USE ShowRoom
INSERT INTO Cars
VALUES
(1, 'Corrolla', 'Toyota', 1800),
(2, 'City', 'Honda', 1500),
(3, 'C200', 'Mercedez', 2000),
(4, 'Vitz', 'Toyota', 1300),
(5, 'Baleno', 'Suzuki', 1500),
(6, 'C500', 'Mercedez', 5000),
(7, '800', 'BMW', 8000),
(8, 'Mustang', 'Ford', 5000),
(9, '208', 'Peugeot', 5400),
(10, 'Prius', 'Toyota', 3200),
(11, 'Atlas', 'Volkswagen', 5000),
(12, '110', 'Bugatti', 8000),
(13, 'Landcruiser', 'Toyota', 3000),
(14, 'Civic', 'Honda', 1800),
(15, 'Accord', 'Honda', 2000)

RANK Function
The RANK function is used to retrieve ranked rows based on the condition of the
ORDER BY clause. For example, if you want to
find the name of the car with third highest power, you can use RANK Function.

Let’s see RANK Function in action:

SELECT name,company, power,


RANK() OVER(ORDER BY power DESC) AS PowerRank
FROM Cars -- Not Correct RANK()

SELECT name,company, power,


RANK() OVER(PARTITION BY company ORDER BY power DESC) AS PowerRank
FROM Cars -- Correct RANK()

DENSE_RANK Function
The DENSE_RANK function is similar to RANK function however the DENSE_RANK function
does not skip any ranks if there is a
tie between the ranks of the preceding records. Take a look at the following
script.

SELECT name,company, power,


RANK() OVER(PARTITION BY company ORDER BY power DESC) AS PowerRank
FROM Cars

You can see from the output that despite there being a tie between the ranks of the
first two rows, the next rank is not
skipped and has been assigned a value of 2 instead of 3. As with the RANK function,
the PARTITION BY clause can also be
used with the DENSE_RANK function as shown below:

SELECT name,company, power,


DENSE_RANK() OVER(PARTITION BY company ORDER BY power DESC) AS DensePowerRank
FROM Cars

ROW_NUMBER Function
Unlike the RANK and DENSE_RANK functions, the ROW_NUMBER function simply returns
the row number of the sorted records
starting with 1. For example, if RANK and DENSE_RANK functions of the first two
records in the ORDER BY column are equal,
both of them are assigned 1 as their RANK and DENSE_RANK. However, the ROW_NUMBER
function will assign values 1 and 2 to
those rows without taking the fact that they are equally into account. Execute the
following script to see the ROW_NUMBER
function in action.

SELECT name,company, power,


ROW_NUMBER() OVER(ORDER BY power DESC) AS RowRank
FROM Cars
RankD pic5
From the output, you can see that ROW_NUMBER function simply assigns a new row
number to each record irrespective of its value.
The PARTITION BY clause can also be used with ROW_NUMBER function as shown below:

SELECT name, company, power,


ROW_NUMBER() OVER(PARTITION BY company ORDER BY power DESC) AS RowRank
FROM Cars

Similarities between RANK, DENSE_RANK, and ROW_NUMBER Functions


The RANK, DENSE_RANK and ROW_NUMBER Functions have the following similarities:
1- All of them require an order by clause.
2- All of them return an increasing integer with a base value of 1.
3- When combined with a PARTITION BY clause, all of these functions reset the
returned integer value to 1 as we have seen.
4- If there are no duplicated values in the column used by the ORDER BY clause,
these functions return the same output.

To illustrate the last point, let’s create a new table Car1 in the ShowRoom
database with no duplicate values in the power
column. Execute the following script:

USE ShowRoom;

CREATE TABLE Cars1


(
id INT,
name VARCHAR(50) NOT NULL,
company VARCHAR(50) NOT NULL,
power INT NOT NULL
)

INSERT INTO Cars1


VALUES
(1, 'Corrolla', 'Toyota', 1800),
(2, 'City', 'Honda', 1500),
(3, 'C200', 'Mercedez', 2000),
(4, 'Vitz', 'Toyota', 1300),
(5, 'Baleno', 'Suzuki', 2500),
(6, 'C500', 'Mercedez', 5000),
(7, '800', 'BMW', 8000),
(8, 'Mustang', 'Ford', 4000),
(9, '208', 'Peugeot', 5400),
(10, 'Prius', 'Toyota', 3200)
The cars1 table has no duplicate values. Now let’s execute the RANK, DENSE_RANK and
ROW_NUMBER functions on the Cars1 table
ORDER BY power column. Execute the following script:
SELECT name,company, power,
RANK() OVER(ORDER BY power DESC) AS [Rank],
DENSE_RANK() OVER(ORDER BY power DESC) AS [Dense Rank],
ROW_NUMBER() OVER(ORDER BY power DESC) AS [Row Number]
FROM Cars1

/
***********************************************************************************
**********************************/

FROM - Using PIVOT and UNPIVOT


Article
04/05/2022
5 minutes to read
14 contributors

Applies to: SQL Server (all supported versions) Azure SQL Database Azure SQL
Managed Instance Azure Synapse Analytics
Analytics Platform System (PDW)

You can use the PIVOT and UNPIVOT relational operators to change a table-valued
expression into another table.
PIVOT rotates a table-valued expression by turning the unique values from one
column in the expression into multiple
columns in the output. And PIVOT runs aggregations where they're required on any
remaining column values that are wanted
in the final output. UNPIVOT carries out the opposite operation to PIVOT by
rotating columns of a table-valued expression
into column values.

The syntax for PIVOT provides is simpler and more readable than the syntax that may
otherwise be specified in a complex
series of SELECT...CASE statements. For a complete description of the syntax for
PIVOT, see FROM (Transact-SQL).

Syntax
The following syntax summarizes how to use the PIVOT operator.

syntaxsql

Copy
SELECT <non-pivoted column>,
[first pivoted column] AS <column name>,
[second pivoted column] AS <column name>,
...
[last pivoted column] AS <column name>
FROM
(<SELECT query that produces the data>)
AS <alias for the source query>
PIVOT
(
<aggregation function>(<column being aggregated>)
FOR
[<column that contains the values that will become column headers>]
IN ( [first pivoted column], [second pivoted column],
... [last pivoted column])
) AS <alias for the pivot table>
<optional ORDER BY clause>;

Remarks
The column identifiers in the UNPIVOT clause follow the catalog collation. For SQL
Database, the collation is always
SQL_Latin1_General_CP1_CI_AS. For SQL Server partially contained databases, the
collation is always
Latin1_General_100_CI_AS_KS_WS_SC. If the column is combined with other columns,
then a collate clause (COLLATE DATABASE_DEFAULT)
is required to avoid conflicts.

Basic PIVOT Example


The following code example produces a two-column table that has four rows.

SQL

Copy
USE AdventureWorks2014 ;
GO
SELECT DaysToManufacture, AVG(StandardCost) AS AverageCost
FROM Production.Product
GROUP BY DaysToManufacture;
Here is the result set.

Copy
DaysToManufacture AverageCost
----------------- -----------
0 5.0885
1 223.88
2 359.1082
4 949.4105

No products are defined with three DaysToManufacture.

The following code displays the same result, pivoted so that the DaysToManufacture
values become the column headings.
A column is provided for three [3] days, even though the results are NULL.

SQL

Copy
-- Pivot table with one row and five columns
SELECT 'AverageCost' AS Cost_Sorted_By_Production_Days,
[0], [1], [2], [3], [4]
FROM
(
SELECT DaysToManufacture, StandardCost
FROM Production.Product
) AS SourceTable
PIVOT
(
AVG(StandardCost)
FOR DaysToManufacture IN ([0], [1], [2], [3], [4])
) AS PivotTable;

Here is the result set.


Copy
Cost_Sorted_By_Production_Days 0 1 2 3 4

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


-----------
AverageCost 5.0885 223.88 359.1082 NULL
949.4105

Complex PIVOT Example


A common scenario where PIVOT can be useful is when you want to generate cross-
tabulation reports to give a
summary of the data. For example, suppose you want to query the PurchaseOrderHeader
table in the AdventureWorks2014
sample database to determine the number of purchase orders placed by certain
employees. The following query provides
this report, ordered by vendor.

SQL

Copy

USE AdventureWorks2014;

GO
SELECT VendorID, [250] AS Emp1, [251] AS Emp2, [256] AS Emp3, [257] AS Emp4, [260]
AS Emp5
FROM
(SELECT PurchaseOrderID, EmployeeID, VendorID
FROM Purchasing.PurchaseOrderHeader) p
PIVOT
(
COUNT (PurchaseOrderID)
FOR EmployeeID IN
( [250], [251], [256], [257], [260] )
) AS pvt
ORDER BY pvt.VendorID;
Here is a partial result set.

Copy
VendorID Emp1 Emp2 Emp3 Emp4 Emp5
----------- ----------- ----------- ----------- ----------- -----------
1492 2 5 4 4 4
1494 2 5 4 5 4
1496 2 4 4 5 5
1498 2 5 4 4 4
1500 3 4 4 5 4
The results returned by this subselect statement are pivoted on the EmployeeID
column.

SQL

Copy
SELECT PurchaseOrderID, EmployeeID, VendorID
FROM PurchaseOrderHeader;
The unique values returned by the EmployeeID column become fields in the final
result set. As such, there's a column for
each EmployeeID number specified in the pivot clause: in this case employees 250,
251, 256, 257, and 260. The PurchaseOrderID
column serves as the value column, against which the columns returned in the final
output, which are called the grouping
columns, are grouped. In this case, the grouping columns are aggregated by the
COUNT function. Notice that a warning message
appears that indicates that any null values appearing in the PurchaseOrderID column
weren't considered when computing the
COUNT for each employee.

Important

When aggregate functions are used with PIVOT, the presence of any null values in
the value column are not considered when
computing an aggregation.

UNPIVOT Example
UNPIVOT carries out almost the reverse operation of PIVOT, by rotating columns into
rows. Suppose the table produced in
the previous example is stored in the database as pvt, and you want to rotate the
column identifiers Emp1, Emp2, Emp3, Emp4,
and Emp5 into row values that correspond to a particular vendor. As such, you must
identify two additional columns. The column
that will contain the column values that you're rotating (Emp1, Emp2,...) will be
called Employee, and the column that will
hold the values that currently exist under the columns being rotated will be called
Orders. These columns correspond to the
pivot_column and value_column, respectively, in the Transact-SQL definition. Here
is the query.

SQL

Copy
-- Create the table and insert values as portrayed in the previous example.
CREATE TABLE pvt (VendorID INT, Emp1 INT, Emp2 INT,
Emp3 INT, Emp4 INT, Emp5 INT);
GO
INSERT INTO pvt VALUES (1,4,3,5,4,4);
INSERT INTO pvt VALUES (2,4,1,5,5,5);
INSERT INTO pvt VALUES (3,4,3,5,4,4);
INSERT INTO pvt VALUES (4,4,2,5,5,4);
INSERT INTO pvt VALUES (5,5,1,5,5,5);
GO
-- Unpivot the table.
SELECT VendorID, Employee, Orders
FROM
(SELECT VendorID, Emp1, Emp2, Emp3, Emp4, Emp5
FROM pvt) p
UNPIVOT
(Orders FOR Employee IN
(Emp1, Emp2, Emp3, Emp4, Emp5)
)AS unpvt;
GO
Here is a partial result set.

Copy
VendorID Employee Orders
----------- ----------- ------
1 Emp1 4
1 Emp2 3
1 Emp3 5
1 Emp4 4
1 Emp5 4
2 Emp1 4
2 Emp2 1
2 Emp3 5
2 Emp4 5
2 Emp5 5
...
Notice that UNPIVOT isn't the exact reverse of PIVOT. PIVOT carries out an
aggregation and merges possible multiple rows
into a single row in the output. UNPIVOT doesn't reproduce the original table-
valued expression result because rows have
been merged. Also, null values in the input of UNPIVOT disappear in the output.
When the values disappear, it shows that
there may have been original null values in the input before the PIVOT operation.

The Sales.vSalesPersonSalesByFiscalYears view in the AdventureWorks2019 sample


database uses PIVOT to return the total
sales for each salesperson, for each fiscal year. To script the view in SQL Server
Management Studio, in Object Explorer,
locate the view under the Views folder for the AdventureWorks2019 database. Right-
click the view name, and then select
Script View as.

/
***********************************************************************************
**********************************/

Fortunately, you now have a great new feature called PIVOT for presenting any query
in the crosstab format using a new operator, appropriately named pivot . Here is
how you write the query:

Copy
Copied to ClipboardError: Could not Copy

select * from (
select times_purchased, state_code
from customers t
)
pivot
(
count(state_code)
for state_code in ('NY','CT','NJ','FL','MO')
)
order by times_purchased
/

select * from (
select times_purchased as "Puchase Frequency", state_code
from customers t
)
pivot
(
count(state_code)
for state_code in ('NY' as "New York",'CT' "Connecticut",'NJ' "New Jersey",'FL'
"Florida",'MO' as "Missouri")
)
order by 1
/

select *
from cust_matrix
unpivot
(
state_counts
for state_code in ("New York","Conn","New Jersey","Florida","Missouri")
)
order by "Puchase Frequency", state_code
/

select value
from
(
(
select
'a' v1,
'e' v2,
'i' v3,
'o' v4,
'u' v5
from dual
)
unpivot
(
value
for value_type in
(v1,v2,v3,v4,v5)
)
)
/
Here is the output:

V
-
a
e
i
o
u

Well, there is another clause in the pivot operation, XML, that allows you to
create the pivoted output as XML where you can
specify a special clause, ANY, instead of literal values. Here is the example:

Copy
Copied to ClipboardError: Could not Copy

select * from (
select times_purchased as "Purchase Frequency", state_code
from customers t
)
pivot xml
(
count(state_code)
for state_code in (any)
)
order by 1
/

The output comes back as CLOB so make sure the LONGSIZE is set to a large value
before running the query.

SQL> set long 99999

There are two distinct differences in this query (shown in bold) compared to the
original pivot operation. First,
you specified a clause, pivot xml, instead of just pivot. It creates the output in
XML. Second, the for clause shows
for state_code in (any) instead of a long list of state_code values. The XML
notation allows you to use the ANY keyword
and you don't need to enter the state_code values. Here is the output:

Purchase Frequency STATE_CODE_XML


------------------ --------------------------------------------------
1 <PivotSet><item><column name = "STATE_CODE">CT</co
lumn><column name = "COUNT(STATE_CODE)">165</colum
n></item><item><column name = "STATE_CODE">NY</col
umn><column name = "COUNT(STATE_CODE)">33048</colu
mn></item></PivotSet>

2 <PivotSet><item><column name = "STATE_CODE">CT</co


lumn><column name = "COUNT(STATE_CODE)">179</colum
n></item><item><column name = "STATE_CODE">NY</col
umn><column name = "COUNT(STATE_CODE)">33151</colu
mn></item></PivotSet>

... and so on ...


As you can see, the column STATE_CODE_XML is XMLTYPE, where the root element is
<PivotSet>. Each value is represented as a
name-value element pair. You can use the output in any XML parser to produce more
useful output.

In addition to the ANY clause, you can write a subquery. Suppose you have a list of
preferred states and you want to select
the rows for those states only. You placed the preferred states in a new table
called preferred_states:

/
***********************************************************************************
***********************************/
Oracle / PLSQL: PIVOT Clause
This Oracle tutorial explains how to use the Oracle PIVOT clause with syntax and
examples.

Description
The Oracle PIVOT clause allows you to write a cross-tabulation query starting in
Oracle 11g. This means that you can aggregate your results and rotate rows into
columns.

Syntax
The syntax for the PIVOT clause in Oracle/PLSQL is:

SELECT * FROM
(
SELECT column1, column2
FROM tables
WHERE conditions
)
PIVOT
(
aggregate_function(column2)
FOR column2
IN ( expr1, expr2, ... expr_n) | subquery
)
ORDER BY expression [ ASC | DESC ];

Parameters or Arguments
aggregate_function
It can be a function such as SUM, COUNT, MIN, MAX, or AVG functions.
IN ( expr1, expr2, ... expr_n )
A list of values for column2 to pivot into headings in the cross-tabulation query
results.

subquery
It can be used instead of a list of values. In this case, the results of the
subquery would be used to determine
the values for column2 to pivot into headings in the cross-tabulation query
results.

Applies To
The PIVOT clause can be used in the following versions of Oracle/PLSQL:

Oracle 12c, Oracle 11g


Example
Let's look at how to use the PIVOT clause in Oracle.

We will base our example on a table called orders with the following definition:

CREATE TABLE orders


( order_id integer NOT NULL,
customer_ref varchar2(50) NOT NULL,
order_date date,
product_id integer,
quantity integer,
CONSTRAINT orders_pk PRIMARY KEY (order_id)
);

To show you the data for this example, we will select the records from the orders
table with the following SELECT statement:

SELECT order_id, customer_ref, product_id


FROM orders
ORDER BY order_id;
These are the records in the orders table. We will be using these records to
demonstrate how the PIVOT clause works:

order_id customer_ref product_id


50001 SMITH 10
50002 SMITH 20
50003 ANDERSON 30
50004 ANDERSON 40
50005 JONES 10
50006 JONES 20
50007 SMITH 20
50008 SMITH 10
50009 SMITH 20

Now, let's create our cross-tabulation query using the following PIVOT clause:

SELECT * FROM
(
SELECT customer_ref, product_id
FROM orders
)
PIVOT
(
COUNT(product_id)
FOR product_id IN (10, 20, 30)
)
ORDER BY customer_ref;
In this example, the PIVOT clause would return the following results:

customer_ref 10 20 30
ANDERSON 0 0 1
JONES 1 1 0
SMITH 2 3 0

Now, let's break apart the PIVOT clause and explain how it worked.

Specify Fields to Include


First, we want to specify what fields to include in our cross tabulation. In this
example, we want to include the
customer_ref and product_id fields. This is done by the following portion of the
statement:

(
SELECT customer_ref, product_id
FROM orders
)
You can list the columns to be included in any order.

Specify Aggregate Function


Next, we need to specify what aggregate function to use when creating our cross-
tabulation query. You can use any
aggregate such as SUM, COUNT, MIN, MAX, or AVG functions.

In this example, we are going to use the COUNT function. This will count the number
of product_id values that meet
our criteria. This is done by the following portion of the statement:

PIVOT
(
COUNT(product_id)
Specify Pivot Values
Finally, we need to specify what pivot values to include in our results. These will
be used as the column headings
in our cross-tabulation query. You can use either be a list of values enclosed in
parentheses or a subquery to specify
the pivot values.

In this example, we are going to return only the following product_id values: 10,
20, 30. These values will become our
column headings in our cross-tabulation query. Also, note that these values are a
finite list of the product_id values
and will not necessarily contain all possible values.

This is done by the following portion of the statement:

FOR product_id IN (10, 20, 30)


)
Now when we put it all together, we get the following pivot table:

customer_ref 10 20 30
ANDERSON 0 0 1
JONES 1 1 0
SMITH 2 3 0

/
***********************************************************************************
**********************************/

APPTAD INC,

1. No. of Annual Paid Leave


2. Annual Bonus Amount
3. Medical Premium Per pay check
4. 401K matching / Vesting Period
5. If Fidelity is client
* Duration of the Project ???
* Is it new project / Existing Project ???
* Work Location - Remote
6. If need to vist client location
* How is response for the Travel /
Stay Expenses.

/
***********************************************************************************
**********************************/
Hi Sarah,

Thank you for reaching me out, Currently I am working in Bank of America,


Charlotte, NC as a TCS consultant.
I hope I can not accept this job offer.

Let me know any Senior/ Oracle Database Developer position in Charlotte NC area.
Much appreciated 👍 My salary
expectations is $150K Annual+. Benefits. With full time permanent position and Not
interested for the W2 positions.
I am a green card holder.
Regards.

/
***********************************************************************************
**********************************/

/
***********************************************************************************
**********************************/
/
***********************************************************************************
**********************************/

You might also like