Oracle_Functions_01
Oracle_Functions_01
***********************************************************************************
**********************************/
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.
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;
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):
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.
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.
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:
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.
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;
/
***********************************************************************************
**********************************/
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.
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
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;
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.
/
***********************************************************************************
**********************************/
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.
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:
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:
We will base our example on a table called orders with the following definition:
To show you the data for this example, we will select the records from the orders
table with the following SELECT statement:
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.
(
SELECT customer_ref, product_id
FROM orders
)
You can list the columns to be included in any order.
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.
customer_ref 10 20 30
ANDERSON 0 0 1
JONES 1 1 0
SMITH 2 3 0
/
***********************************************************************************
**********************************/
APPTAD INC,
/
***********************************************************************************
**********************************/
Hi Sarah,
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.
/
***********************************************************************************
**********************************/
/
***********************************************************************************
**********************************/
/
***********************************************************************************
**********************************/