PLSQL New Prashant

You might also like

Download as docx, pdf, or txt
Download as docx, pdf, or txt
You are on page 1of 18

Oracle/PLSQL: LAG Function

This Oracle tutorial explains how to use the Oracle/PLSQL LAG function with


syntax and examples.

Description
The Oracle/PLSQL LAG function is an analytic function that lets you query more than
one row in a table at a time without having to join the table to itself. It returns values
from a previous row in the table. To return a value from the next row, try using
the LEAD function.

Syntax
The syntax for the LAG function in Oracle/PLSQL is:

LAG ( expression [, offset [, default] ] )


OVER ( [ query_partition_clause ] order_by_clause )

Parameters or Arguments
expression
An expression that can contain other built-in functions, but can not contain
any analytic functions.
offset
Optional. It is the physical offset from the current row in the table. If this
parameter is omitted, the default is 1.
default
Optional. It is the value that is returned if the offset goes out of the bounds of
the table. If this parameter is omitted, the default is null.
query_partition_clause
Optional. It is used to partition the results into groups based on one or more
expressions.
order_by_clause
Optional. It is used to order the data within each partition.

Example
The LAG function can be used in Oracle/PLSQL.

Let's look at an example. If we had an orders table that contained the following data:
PRODUCT_I
ORDER_DATE QTY
D

2007/09/25 1000 20

2007/09/26 2000 15

2007/09/27 1000 8

2007/09/28 2000 12

2007/09/29 2000 2

2007/09/30 1000 4

And we ran the following SQL statement:

SELECT product_id, order_date,


LAG (order_date,1) OVER (ORDER BY order_date) AS prev_order_date
FROM orders;

It would return the following result:

PRODUCT_I
ORDER_DATE PREV_ORDER_DATE
D

1000 2007/09/25 NULL

2000 2007/09/26 2007/09/25

1000 2007/09/27 2007/09/26

2000 2007/09/28 2007/09/27

2000 2007/09/29 2007/09/28

1000 2007/09/30 2007/09/29


In this example, the LAG function will sort in ascending order all of
the order_date values in the orders table and then return the
previous order_date since we used an offset of 1.

If we had used an offset of 2 instead, it would have returned the order_date from 2


orders earlier. If we had used an offset of 3, it would have returned
theorder_date from 3 orders earlier....and so on.

Using Partitions
Now let's look at a more complex example where we use a query partition clause to
return the previous order_date for each product_id.

Enter the following SQL statement:

SELECT product_id, order_date,


LAG (order_date,1) OVER (PARTITION BY product_id ORDER BY order_date)
AS prev_order_date
FROM orders;

It would return the following result:

PRODUCT_I
ORDER_DATE PREV_ORDER_DATE
D

1000 2007/09/25 NULL

1000 2007/09/27 2007/09/25

1000 2007/09/30 2007/09/27

2000 2007/09/26 NULL

2000 2007/09/28 2007/09/26

2000 2007/09/29 2007/09/28

In this example, the LAG function will partition the results by product_id and then sort
by order_date as indicated by PARTITION BY product_id ORDER BY order_date. This
means that the LAG function will only evaluate an order_date value if
the product_id matches the current record's product_id. When a newproduct_id is
encountered, the LAG function will restart its calculations and use the
appropriate product_id partition.

As you can see, the 1st record in the result set has a value of NULL for
the prev_order_date because it is the first record for the partition where product_id is
1000 (sorted by order_date) so there is no lower order_date value. This is also true
for the 4th record where the product_id is 2000.
Oracle/PLSQL: LEAD Function
This Oracle tutorial explains how to use the Oracle/PLSQL LEAD function with
syntax and examples.

Description
The Oracle/PLSQL LEAD function is an analytic function that lets you query more
than one row in a table at a time without having to join the table to itself. It returns
values from the next row in the table. To return a value from a previous row, try using
the LAG function.

Syntax
The syntax for the LEAD function in Oracle/PLSQL is:

LEAD ( expression [, offset [, default] ] )


OVER ( [ query_partition_clause ] order_by_clause )

Parameters or Arguments
expression
An expression that can contain other built-in functions, but can not contain
any analytic functions.
offset
Optional. It is the physical offset from the current row in the table. If this
parameter is omitted, the default is 1.
default
Optional. It is the value that is returned if the offset goes out of the bounds of
the table. If this parameter is omitted, the default is null.
query_partition_clause
Optional. It is used to partition the results into groups based on one or more
expressions.
order_by_clause
Optional. It is used to order the data within each partition.

Example
The LEAD function can be used in Oracle/PLSQL.

Let's look at an example. If we had an orders table that contained the following data:
PRODUCT_I
ORDER_DATE QTY
D

2007/09/25 1000 20

2007/09/26 2000 15

2007/09/27 1000 8

2007/09/28 2000 12

2007/09/29 2000 2

2007/09/30 1000 4

And we ran the following SQL statement:

SELECT product_id, order_date,


LEAD (order_date,1) OVER (ORDER BY order_date) AS next_order_date
FROM orders;

It would return the following result:

PRODUCT_I
ORDER_DATE NEXT_ORDER_DATE
D

1000 2007/09/25 2007/09/26

2000 2007/09/26 2007/09/27

1000 2007/09/27 2007/09/28

2000 2007/09/28 2007/09/29

2000 2007/09/29 2007/09/30

1000 2007/09/30 NULL


In this example, the LEAD function will sort in ascending order all of
the order_date values in the orders table and then return the next order_date since
we used an offset of 1.

If we had used an offset of 2 instead, it would have returned the order_date from 2


orders later. If we had used an offset of 3, it would have returned theorder_date from
3 orders later....and so on.

Using Partitions
Now let's look at a more complex example where we use a query partition clause to
return the next order_date for each product_id.

Enter the following SQL statement:

SELECT product_id, order_date,


LEAD (order_date,1) OVER (PARTITION BY product_id ORDER BY order_date)
AS next_order_date
FROM orders;

It would return the following result:

PRODUCT_I
ORDER_DATE NEXT_ORDER_DATE
D

1000 2007/09/25 2007/09/27

1000 2007/09/27 2007/09/30

1000 2007/09/30 NULL

2000 2007/09/26 2007/09/28

2000 2007/09/28 2007/09/29

2000 2007/09/29 NULL

In this example, the LEAD function will partition the results by product_id and then
sort by order_date as indicated by PARTITION BY product_id ORDER BY order_date.
This means that the LEAD function will only evaluate an order_date value if
the product_id matches the current record's product_id. When a newproduct_id is
encountered, the LEAD function will restart its calculations and use the
appropriate product_id partition.

As you can see, the 3rd record in the result set has a value of NULL for
the next_order_date because it is the last record for the partition where product_id is
1000 (sorted by order_date). This is also true for the 6th record where
the product_id is 2000.
Oracle/PLSQL: RANK Function
This Oracle tutorial explains how to use the Oracle/PLSQL RANK function with
syntax and examples.

Description
The Oracle/PLSQL RANK function returns the rank of a value in a group of values. It
is very similar to the DENSE_RANK function. However, the rank function can cause
non-consecutive rankings if the tested values are the same. Whereas,
the DENSE_RANK function will always result in consecutive rankings.

The RANK function can be used two ways - as an Aggregate function or as an


Analytic function.

RANK Function Syntax #1 - Used as an Aggregate Function


As an Aggregate function, the RANK function returns the rank of a row within a
group of rows.

The syntax for the RANK function when used as an Aggregate function is:

RANK( expr1 [, expr2, ... expr_n ] ) WITHIN GROUP ( ORDER BY expr1 [,


expr_2, ... expr_n ] )

Parameters or Arguments
expr1
First expression which identifies a unique row in the group.
expr2, ... expr_n
Optional. Additional expressions which identifies a unique row in the group.

Note

 There must be the same number of expressions in the first expression list as
there is in the ORDER BY clause.
 The expression lists match by position so the data types must be compatible
between the expressions in the first expression list as in the ORDER BY
clause.
Applies To
The RANK function can be used in the following versions of Oracle/PLSQL:

 Oracle 12c, Oracle 11g, Oracle 10g, Oracle 9i

Example (as an Aggregate Function)


Let's look at some Oracle RANK function examples and explore how to use the
RANK function in Oracle/PLSQL.

For example:

select RANK(1000, 500) WITHIN GROUP (ORDER BY salary, bonus)


from employees;

The SQL statement above would return the rank of an employee with a salary of
$1,000 and a bonus of $500 from within the employees table.

RANK Function Syntax #2 - Used as an Analytic Function


As an Analytic function, the RANK function returns the rank of each row of a query
with respective to the other rows.

The syntax for the RANK function when used as an Analytic function is:

rank() OVER ( [ query_partition_clause] ORDER BY clause )

Applies To
The RANK function can be used in the following versions of Oracle/PLSQL:

 Oracle 11g, Oracle 10g, Oracle 9i, Oracle 8i

Example (as an Analytic Function)

select employee_name, salary,


RANK() OVER (PARTITION BY department ORDER BY salary)
from employees
where department = 'Marketing';
The SQL statement above would return all employees who work in the Marketing
department and then calculate a rank for each unique salary in the Marketing
department. If two employees had the same salary, the RANK function would return
the same rank for both employees. However, this will cause a gap in the ranks (ie:
non-consecutive ranks). This is quite different from the DENSE_RANK
function which generates consecutive rankings.
Oracle/PLSQL: DENSE_RANK Function
This Oracle tutorial explains how to use the Oracle/PLSQL DENSE_RANK
function with syntax and examples.

Description
The Oracle/PLSQL DENSE_RANK function returns the rank of a row in a group of
rows. It is very similar to the RANK function. However, the RANK function can cause
non-consecutive rankings if the tested values are the same. Whereas, the
DENSE_RANK function will always result in consecutive rankings.

The DENSE_RANK function can be used two ways - as an Aggregate function or as


an Analytic function.

DENSE_RANK Function Syntax #1 - Used as an Aggregate Function


As an Aggregate function, the DENSE_RANK function returns the dense rank of a
row within a group of rows.

The syntax for the DENSE_RANK function when used as an Aggregate function is:

DENSE_RANK( expression1, ... expression_n ) WITHIN GROUP ( ORDER BY


expression1, ... expression_n )

Parameters or Arguments
expression1 .. expression_n
One or more expressions which identify a unique row in the group.

Note

 There must be the same number of expressions in the first expression list as
there is in the ORDER BY clause.
 The expression lists match by position so the data types must be compatible
between the expressions in the first expression list as in the ORDER BY
clause.

Applies To
The DENSE_RANK function can be used in the following versions of Oracle/PLSQL:
 Oracle 12c, Oracle 11g, Oracle 10g, Oracle 9i

Example (as an Aggregate Function)


Let's look at some Oracle DENSE_RANK function examples and explore how to use
the DENSE_RANK function in Oracle/PLSQL.

For example:

select DENSE_RANK(1000, 500) WITHIN GROUP (ORDER BY salary, bonus)


from employees;

The SQL statement above would return the dense rank of an employee with a salary
of $1,000 and a bonus of $500 from within the employees table.

DENSE_RANK Function Syntax #2 - Used as an Analytic Function


As an Analytic function, the DENSE_RANK function returns the rank of each row of a
query with respective to the other rows.

The syntax for the DENSE_RANK function when used as an Analytic function is:

DENSE_RANK() OVER ( [ query_partition_clause] ORDER BY clause )

Applies To
The DENSE_RANK function can be used in the following versions of Oracle/PLSQL:

 Oracle 11g, Oracle 10g, Oracle 9i, Oracle 8i

Example (as an Analytic Function)


Let's look at some Oracle DENSE_RANK function examples and explore how to use
the DENSE_RANK function in Oracle/PLSQL.

For example:

select employee_name, salary,


DENSE_RANK() OVER (PARTITION BY department ORDER BY salary)
from employees
where department = 'Marketing';
The SQL statement above would return all employees who work in the Marketing
department and then calculate a rank for each unique salary in the Marketing
department. If two employees had the same salary, the DENSE_RANK function
would return the same rank for both employees.
TIP: OVER AND PARTITION BY
OCTOBER 5, 2010 JEN MCCOWN 20 COMMENTS

Here’s a quick summary of OVER and PARTITION BY (new in SQL 2005), for the
uninitiated or forgetful…

OVER
OVER allows you to get aggregate information without using a GROUP BY. In other words,
you can retrieve detail rows, and get aggregate data alongside it. For example, this query:

SELECT SUM(Cost) OVER () AS Cost


, OrderNum
FROM Orders
Will return something like this:

Cost  OrderNum
10.00 345
10.00 346
10.00 347
10.00 348
Quick translation:

 SUM(cost) – get me the sum of the COST column


 OVER – for the set of rows….
 () – …that encompasses the entire result set.

OVER(PARTITION BY)
OVER, as used in our previous example, exposes the entire resultset to the
aggregation…”Cost” was the sum of all [Cost]  in the resultset.  We can break up that
resultset into partitions with the use of PARTITION BY:
SELECT SUM(Cost) OVER (PARTITION BY CustomerNo) AS Cost
, OrderNum
, CustomerNo
FROM Orders
My partition is by CustomerNo – each “window” of a single customer’s orders will be
treated separately from each other “window”….I’ll get the sum of cost for Customer 1, and
then the sum for Customer 2:
Cost  OrderNum   CustomerNo
8.00 345        1
8.00 346        1
8.00 347        1
2.00 348        2
The translation here is:

 SUM(cost) – get me the sum of the COST column


 OVER – for the set of rows….
 (PARTITION BY CustomerNo) – …that have the same CustomerNo.
1) Find highest salary/salaries using DENSE_RANK() function

select * from (select empno,salary,dense_rank() over(order by


salary desc) as rk from emp) where rk = 1;

EMPNO     SALARY       RK


———-      ———-       ———-
10               12000            1

2) Find 2nd highest salary/salaries


using DENSE_RANK() function

select * from (select empno,salary,dense_rank() over(order by


salary desc) as rk from emp) where rk = 2;

EMPNO       SALARY          RK


———-           ———-         ———-
11                 10000               2
12                 10000               2

If you replace 2 with N in above query it will provide Nth highest


salary/salaries.

3. Find 2nd highest salary using ROW_NUMBER() function

select * from (select empno, salary, row_number() over(order by


salary desc) rk from emp order by salary desc ) where rk = 2;

EMPNO       SALARY          RK


———-           ———-         ———-
11                 10000               2

Note that this query will not give multiple records if there are


employees with same salaries ( compare query (2) and (3) )

4. Find 2nd highest salary using ROWNUM


select * from (select empno, salary,rownum rk from emp order by
salary desc) where rk = 2;

EMPNO       SALARY          RK


———-           ———-         ———-
11                 10000               2

Note that this query also will not give multiple records if there are
employees with same salaries ( compare query (2) and (4) )

Conclusion :- Use DENSE_RANK, ROW_NUMBER(),


ROWNUM with respect to the requirement. As per my experience
query with ROW_NUMBER() is most appropriate and good for
performance.

You might also like