Skip to Main Content

SQL & PL/SQL

Announcement

For appeals, questions and feedback about Oracle Forums, please email oracle-forums-moderators_us@oracle.com. Technical questions should be asked in the appropriate category. Thank you!

Analytic function - LAG() with dynamic offset value

Sravan GereddyJun 7 2017 — edited Jun 7 2017

Hi All,

We have a requirement to perform arithmetic operations on values of different rows of a column. Here is an illustration of the requirement.

There are 3 columns, Plant, Mineral and Value. Each plant has a set of minerals and each mineral has a value. Each plant can have any number of minerals, out of which M1 is mandatory. The requirement is to report a column(column 4 below), whose value is the value associated to the mineral - value of mineral M1 of that plant.

pastedImage_1.png

So coded the below SQL fulfills the requirement, but I used a temporary set q2. Is there any way I can put the same logic in a single query without inner queries as well. I'm trying to use a ROW_NUMBER() analytic function in LAG()'s offset but SQL throws an error as, nested analytic functions is not supported. Is there any other way to user dynamic offset value in LAG () without using analytic functions?

Current Working Solution

WITH q1 AS (

SELECT 'A' plant,'M1' mineral,'1' value FROM DUAL UNION ALL

SELECT 'A','M2','2' FROM DUAL UNION ALL

SELECT 'A','M3','3' FROM DUAL UNION ALL

SELECT 'A','M4','4' FROM DUAL UNION ALL

SELECT 'A','M5','5' FROM DUAL UNION ALL

SELECT 'A','M6','6' FROM DUAL UNION ALL

SELECT 'A','M7','7' FROM DUAL UNION ALL

SELECT 'A','M8','8' FROM DUAL UNION ALL

SELECT 'B','M1','21' FROM DUAL UNION ALL

SELECT 'B','M2','12' FROM DUAL UNION ALL

SELECT 'B','M3','13' FROM DUAL UNION ALL

SELECT 'B','M4','14' FROM DUAL UNION ALL

SELECT 'B','M5','15' FROM DUAL UNION ALL

SELECT 'B','M6','16' FROM DUAL UNION ALL

SELECT 'B','M7','17' FROM DUAL UNION ALL

SELECT 'B','M8','18' FROM DUAL UNION ALL

SELECT 'C','M1','181' FROM DUAL UNION ALL

SELECT 'C','M2','112' FROM DUAL UNION ALL

SELECT 'C','M3','113' FROM DUAL UNION ALL

SELECT 'C','M4','114' FROM DUAL UNION ALL

SELECT 'C','M5','115' FROM DUAL UNION ALL

SELECT 'C','M6','116' FROM DUAL UNION ALL

SELECT 'C','M7','117' FROM DUAL UNION ALL

SELECT 'C','M8','118' FROM DUAL

),q2 AS (

SELECT q1.\*,

       ROW\_NUMBER() OVER(PARTITION BY

        plant

        ORDER BY

            CASE

                WHEN mineral = 'MOISTURE' THEN 1

                ELSE

                    2

            END

    ) row\_id

FROM

    q1

) SELECT q2.*,

   LAG(

    q2.value,

    q2.row\_id - 1,

    0

) OVER(PARTITION BY

    plant

    ORDER BY

        q2.row\_id

) lag\_val

FROM

q2;
This post has been answered by Stew Ashton on Jun 7 2017
Jump to Answer
Comments
Locked Post
New comments cannot be posted to this locked post.
Post Details
Locked on Jul 5 2017
Added on Jun 7 2017
8 comments
1,619 views