Home » SQL & PL/SQL » SQL & PL/SQL » Get most recent Value in one row only. (6 merged) (ORACLE)
Get most recent Value in one row only. (6 merged) [message #689980] Wed, 11 September 2024 09:06 Go to next message
Nicha
Messages: 34
Registered: March 2020
Member
I have a table with accounts and their respective interest rate values (JUR) and bank spread values (SPR) information. For each account I have the history of the rate information by date (DINIVALI - date field). I want to pull the most recent interest rate (JUR) and spread (SPR) information per account.

The CCONDLIQ field has 2 Values : (JUR) for interest rate values; (SPR) for Spread values.

/forum/fa/14812/0/


I need to obtain, in a single record, both the most recent interest rate (JUR) and Spread (SPR) associated with the account, as shown in the Query Result.

Table data:

CREATE TABLE Table1
( 
  CCONTA       VARCHAR2(15)            NOT NULL,
  CCONDLIQ     VARCHAR2(3)             NOT NULL,
  DINIVALI     DATE                    NOT NULL,
  VTXJURO      NUMBER(8,5)             NOT NULL
)

insert into Table1 values ('000315394751096','JUR',To_date('2022-09-02','YYYY-MM-DD'));
insert into Table1 values ('000315394751096','JUR',To_date('2022-09-03','YYYY-MM-DD'));
insert into Table1 values ('000315394751096','JUR',To_date('2023-03-03','YYYY-MM-DD'));
insert into Table1 values ('000315394751096','JUR',To_date('2023-09-03','YYYY-MM-DD'));
insert into Table1 values ('000315394751096','JUR',To_date('2024-03-03','YYYY-MM-DD'));
insert into Table1 values ('000315394751096','JUR',To_date('2024-07-03','YYYY-MM-DD'));
insert into Table1 values ('000315394751096','SPR',To_date('2022-02-09','YYYY-MM-DD'));
insert into Table1 values ('000315394751096','SPR',To_date('2022-09-03','YYYY-MM-DD'));
insert into Table1 values ('000315394751096','SPR',To_date('2023-03-03','YYYY-MM-DD'));
insert into Table1 values ('000315394751096','SPR',To_date('2024-07-03','YYYY-MM-DD'));
The Table "table1 " has more than 59 million records, where the index is "CCONTA, CCONDLIQ, DINIVALI", so the query must befast on performance.

Can anyone help me, please?
Re: Get most recent Value in one row only. (6 merged) [message #689996 is a reply to message #689980] Wed, 11 September 2024 13:35 Go to previous messageGo to next message
Michel Cadot
Messages: 68728
Registered: March 2007
Location: Saint-Maur, France, https...
Senior Member
Account Moderator

Take care of your test case: your INSERT statements are missing VTXJURO values.

One way is:
SQL> select CCONTA,
  2         max(decode(CCONDLIQ, 'JUR', VTXJURO)) keep(dense_rank last order by DINIVALI) VTXJURO_JUR,
  3         max(decode(CCONDLIQ, 'SPR', VTXJURO)) keep(dense_rank last order by DINIVALI) VTXJURO_SPR
  4  from table1
  5  group by CCONTA
  6  order by CCONTA
  7  /
CCONTA          VTXJURO_JUR VTXJURO_SPR
--------------- ----------- -----------
000315394751096         2.9           0
Re: Get most recent Value in one row only. (6 merged) [message #689997 is a reply to message #689996] Wed, 11 September 2024 13:39 Go to previous messageGo to next message
Michel Cadot
Messages: 68728
Registered: March 2007
Location: Saint-Maur, France, https...
Senior Member
Account Moderator

Another way, maybe faster in your case:
SQL> select *
  2  from (select CCONTA, CCONDLIQ,
  3               max(VTXJURO) keep(dense_rank last order by DINIVALI) VTXJURO
  4        from table1
  5        group by CCONTA, CCONDLIQ)
  6  pivot (max(VTXJURO) for CCONDLIQ in ('JUR' as "VTXJURO_JUR",'SPR' as "VTXJURO_SPR"))
  7  /
CCONTA          VTXJURO_JUR VTXJURO_SPR
--------------- ----------- -----------
000315394751096         2.9           0

[Updated on: Wed, 11 September 2024 13:40]

Report message to a moderator

Re: Get most recent Value in one row only. (6 merged) [message #689998 is a reply to message #689997] Thu, 12 September 2024 06:24 Go to previous messageGo to next message
Nicha
Messages: 34
Registered: March 2020
Member
Most apreciated for all your support.
I'm going to test this afternoon, and let you know my feed-back.

My best regards
Re: Get most recent Value in one row only. (6 merged) [message #689999 is a reply to message #689998] Thu, 12 September 2024 09:04 Go to previous messageGo to next message
Nicha
Messages: 34
Registered: March 2020
Member
Many thanks @Michel Cdot.
Work's like a charm.


Do you think that it is possible to add the DINIVALI (Date Field), as shown below?

CCONTA          VTXJURO_JUR DATE_JUR   VTXJURO_SPR DATE_SPR
--------------- ----------- ---------- ----------- ----------
000315394751096         2.9 03-07-2024           0 03-07-2024

[Updated on: Thu, 12 September 2024 09:15]

Report message to a moderator

Re: Get most recent Value in one row only. (6 merged) [message #690000 is a reply to message #689980] Thu, 12 September 2024 09:24 Go to previous messageGo to next message
Nicha
Messages: 34
Registered: March 2020
Member
@Michel Cadot
Do you think that it is possible to add the DINIVALI (Date Field), as shown below?


/forum/fa/14814/0/


Best Regards
Re: Get most recent Value in one row only. (6 merged) [message #690001 is a reply to message #690000] Thu, 12 September 2024 10:15 Go to previous messageGo to next message
Nicha
Messages: 34
Registered: March 2020
Member
Sorry @Michel Cadot.

I've been testing your Query, and notest that it's not working in the example Below: Your Query is ggiving Null values on SPR.


/forum/fa/14816/0/


CREATE TABLE Table1
( 
  CCONTA       VARCHAR2(15)            NOT NULL,
  CCONDLIQ     VARCHAR2(3)             NOT NULL,
  DINIVALI     DATE                    NOT NULL,
  VTXJURO      NUMBER(8,5)             NOT NULL
)

insert into Table1 values ('000310516085096','JUR',To_date('2023-10-03','YYYY-MM-DD'),6.649);
insert into Table1 values ('000310516085096','JUR',To_date('2022-10-03','YYYY-MM-DD'),4.733);
insert into Table1 values ('000310516085096','SPR',To_date('2022-10-03','YYYY-MM-DD'),2.5);
insert into Table1 values ('000310516085096','JUR',To_date('2021-10-03','YYYY-MM-DD'),2.008);
insert into Table1 values ('000310516085096','JUR',To_date('2020-10-03','YYYY-MM-DD'),2.085);
insert into Table1 values ('000310516085096','JUR',To_date('2019-10-03','YYYY-MM-DD'),2.161);
insert into Table1 values ('000310516085096','JUR',To_date('2018-10-03','YYYY-MM-DD'),2.334);
insert into Table1 values ('000310516085096','JUR',To_date('2017-10-03','YYYY-MM-DD'),2.332);
insert into Table1 values ('000310516085096','JUR',To_date('2016-09-30','YYYY-MM-DD'),2.452);
insert into Table1 values ('000310516085096','SPR',To_date('2016-09-30','YYYY-MM-DD'),2.5);

Sorry. Can you take a look please?

Thank you
Re: Get most recent Value in one row only. (6 merged) [message #690002 is a reply to message #690001] Thu, 12 September 2024 11:04 Go to previous messageGo to next message
Michel Cadot
Messages: 68728
Registered: March 2007
Location: Saint-Maur, France, https...
Senior Member
Account Moderator

Use the second query (which is better... and correct Smile ):
SQL> select *
  2  from (select CCONTA, CCONDLIQ, max(DINIVALI) DINIVALI,
  3               max(VTXJURO) keep(dense_rank last order by DINIVALI) VTXJURO
  4        from table1
  5        group by CCONTA, CCONDLIQ)
  6  pivot (max(VTXJURO) as "VTXJURO", max(DINIVALI) as "DINIVALI" for CCONDLIQ in ('JUR','SPR'))
  7  /
CCONTA          'JUR'_VTXJURO 'JUR'_DINIV 'SPR'_VTXJURO 'SPR'_DINIV
--------------- ------------- ----------- ------------- -----------
000310516085096         6.649 03-OCT-2023           2.5 03-OCT-2022

[Updated on: Thu, 12 September 2024 11:08]

Report message to a moderator

Re: Get most recent Value in one row only. (6 merged) [message #690003 is a reply to message #690002] Thu, 12 September 2024 11:30 Go to previous messageGo to next message
Nicha
Messages: 34
Registered: March 2020
Member
Hi, thank you once more.


I've tried with both where clause or Having clause, and neither one is working.
What am I doing wrong?
Bothe are returning no records.

select *
    from (select CCONTA, CCONDLIQ, max(DINIVALI) DINIVALI,
                 max(VTXJURO) keep(dense_rank last order by DINIVALI) VTXJURO
        from Table1
        --where cconta = '00031051608509'

          group by CCONTA, CCONDLIQ
        --  having cconta = '00031051608509'
          )
    pivot (max(VTXJURO) as "VTXJURO", max(DINIVALI) as "DINIVALI" for CCONDLIQ in ('JUR','SPR'))

;
Re: Get most recent Value in one row only. (6 merged) [message #690004 is a reply to message #690003] Thu, 12 September 2024 11:58 Go to previous messageGo to next message
Michel Cadot
Messages: 68728
Registered: March 2007
Location: Saint-Maur, France, https...
Senior Member
Account Moderator

Because there are no "cconta = '00031051608509'" in your table.

Re: Get most recent Value in one row only. (6 merged) [message #690005 is a reply to message #690004] Thu, 12 September 2024 13:17 Go to previous messageGo to next message
Nicha
Messages: 34
Registered: March 2020
Member
This account is on the create table I sent on the 16:15h message.
Re: Get most recent Value in one row only. (6 merged) [message #690006 is a reply to message #690005] Thu, 12 September 2024 14:17 Go to previous messageGo to next message
Michel Cadot
Messages: 68728
Registered: March 2007
Location: Saint-Maur, France, https...
Senior Member
Account Moderator

000310516085096 <> 00031051608509

Re: Get most recent Value in one row only. (6 merged) [message #690007 is a reply to message #690006] Thu, 12 September 2024 14:22 Go to previous messageGo to next message
Nicha
Messages: 34
Registered: March 2020
Member
You are rigth.
Please forguive me.
Can you test with the 00031051608509. I pasted without the 6. Please?

[Updated on: Thu, 12 September 2024 14:23]

Report message to a moderator

Re: Get most recent Value in one row only. (6 merged) [message #690008 is a reply to message #690007] Thu, 12 September 2024 14:57 Go to previous messageGo to next message
Michel Cadot
Messages: 68728
Registered: March 2007
Location: Saint-Maur, France, https...
Senior Member
Account Moderator

With the correct ID both work:
SQL> select *
  2      from (select CCONTA, CCONDLIQ, max(DINIVALI) DINIVALI,
  3                   max(VTXJURO) keep(dense_rank last order by DINIVALI) VTXJURO
  4          from Table1
  5          where cconta = '000310516085096'
  6            group by CCONTA, CCONDLIQ
  7          --  having cconta = '00031051608509'
  8            )
  9      pivot (max(VTXJURO) as "VTXJURO", max(DINIVALI) as "DINIVALI" for CCONDLIQ in ('JUR','SPR'))
 10  /
CCONTA          'JUR'_VTXJURO 'JUR'_DINIV 'SPR'_VTXJURO 'SPR'_DINIV
--------------- ------------- ----------- ------------- -----------
000310516085096         6.649 03-OCT-2023           2.5 03-OCT-2022

1 row selected.

SQL> select *
  2      from (select CCONTA, CCONDLIQ, max(DINIVALI) DINIVALI,
  3                   max(VTXJURO) keep(dense_rank last order by DINIVALI) VTXJURO
  4          from Table1
  5          --where cconta = '00031051608509'
  6
  7            group by CCONTA, CCONDLIQ
  8          having cconta = '000310516085096'
  9            )
 10      pivot (max(VTXJURO) as "VTXJURO", max(DINIVALI) as "DINIVALI" for CCONDLIQ in ('JUR','SPR'))
 11  /
CCONTA          'JUR'_VTXJURO 'JUR'_DINIV 'SPR'_VTXJURO 'SPR'_DINIV
--------------- ------------- ----------- ------------- -----------
000310516085096         6.649 03-OCT-2023           2.5 03-OCT-2022

1 row selected.
Re: Get most recent Value in one row only. (6 merged) [message #690009 is a reply to message #690008] Fri, 13 September 2024 03:40 Go to previous messageGo to next message
Nicha
Messages: 34
Registered: March 2020
Member
Good morning @Michel Cadot

GREAAATTTTT JOB.

Thank you very much.

Can I Ask you, please, a short explanation on how this work's?
Wich is better to use, between Where or Having Clauses?
Or, at least, how the Query creates the aliases ['JUR'_VTXJURO] and ['SPR'_VTXJURO], as they are not in the select clause?
The idea is Substitute de Select * on the outer query, by Select with the field names.

Most apretiated.

P.S. Can you also tell me how can I close this Topic?

[Updated on: Fri, 13 September 2024 07:52]

Report message to a moderator

Re: Get most recent Value in one row only. (6 merged) [message #690010 is a reply to message #690009] Sat, 14 September 2024 03:38 Go to previous messageGo to next message
Michel Cadot
Messages: 68728
Registered: March 2007
Location: Saint-Maur, France, https...
Senior Member
Account Moderator

Quote:
Can I Ask you, please, a short explanation on how this work's?

The inner part returns, for each CCONTA, CCONDLIQ the last date ("max(DINIVALI)" and the VTXJURO value for this one ("max(VTXJURO) keep(dense_rank last order by DINIVALI)"):
SQL> select CCONTA, CCONDLIQ, max(DINIVALI) DINIVALI,
  2               max(VTXJURO) keep(dense_rank last order by DINIVALI) VTXJURO
  3        from table1
  4        group by CCONTA, CCONDLIQ
  5  /
CCONTA          CCO DINIVALI       VTXJURO
--------------- --- ----------- ----------
000310516085096 JUR 03-OCT-2023      6.649
000310516085096 SPR 03-OCT-2022        2.5

2 rows selected.
The PIVOT clause puts these values in a single row per CCONTA.


Quote:
Wich is better to use, between Where or Having Clauses?

Theoretically, WHERE is better as it filters the rows before applying the grouping and computing the SELECT expressions when with HAVING you first compute these values for all groups and then restrict the groups to those indicated by the HAVING clause.
Actually, Oracle optimizer is smart enough to convert the HAVING clause into a WHERE one when appropriate which is the case here.


Quote:
how the Query creates the aliases ['JUR'_VTXJURO] and ['SPR'_VTXJURO]

The aliases are created by Oracle from the PIVOT clause: the first part of the aliases are from the IN part of this clause and the second part from the aggregate expressions of the PIVOT clause:
SQL> select *
  2  from (select CCONTA, CCONDLIQ, max(DINIVALI) DINIVALI,
  3               max(VTXJURO) keep(dense_rank last order by DINIVALI) VTXJURO
  4        from table1
  5        group by CCONTA, CCONDLIQ)
  6  pivot (max(VTXJURO) as "VTXJURO", max(DINIVALI) as "DINIVALI"
  7         for CCONDLIQ in ('JUR' as "JUR",'SPR' as "SPR"))
  8  /
CCONTA          JUR_VTXJURO JUR_DINIVAL SPR_VTXJURO SPR_DINIVAL
--------------- ----------- ----------- ----------- -----------
000310516085096       6.649 03-OCT-2023         2.5 03-OCT-2022
To be clearer:
SQL> select *
  2  from (select CCONTA, CCONDLIQ, max(DINIVALI) DINIVALI,
  3               max(VTXJURO) keep(dense_rank last order by DINIVALI) VTXJURO
  4        from table1
  5        group by CCONTA, CCONDLIQ)
  6  pivot (max(VTXJURO) as "agg1", max(DINIVALI) as "agg2"
  7         for CCONDLIQ in ('JUR' as "val1", 'SPR' as "val2"))
  8  /
CCONTA           val1_agg1 val1_agg2    val2_agg1 val2_agg2
--------------- ---------- ----------- ---------- -----------
000310516085096      6.649 03-OCT-2023        2.5 03-OCT-2022

Quote:
The idea is Substitute de Select * on the outer query, by Select with the field names.

You can of course rename the Oracle aliases as you want in the outer SELECT clause.


Quote:
Can you also tell me how can I close this Topic?

There is no way to close a topic in OraFAQ.

Re: Get most recent Value in one row only. (6 merged) [message #690012 is a reply to message #690010] Sat, 14 September 2024 09:30 Go to previous messageGo to next message
Solomon Yakobson
Messages: 3303
Registered: January 2010
Location: Connecticut, USA
Senior Member
Match recognize solution:

select  cconta,
        jur_vtxjuro vtxjuro_jur,
        jur_dinivali date_jur,
        spr_vtxjuro vtxjuro_spr,
        spr_dinivali date_spr
  from  table1
  match_recognize(
                  partition by cconta,
                               ccondliq
                  order by dinivali
                  measures
                    last(vtxjuro) vtxjuro,
                    last(dinivali) dinivali
                  one row per match
                  pattern(p+)
                  define p as 1 = 1
                 )
  pivot(
        max(vtxjuro) vtxjuro,
        max(dinivali) dinivali
        for ccondliq in ('JUR' jur,'SPR' spr)
       )
/

CCONTA          VTXJURO_JUR DATE_JUR  VTXJURO_SPR DATE_SPR
--------------- ----------- --------- ----------- ---------
000315394751096         2.9 03-JUL-24           0 03-JUL-24

SQL>
SY.
Re: Get most recent Value in one row only. (6 merged) [message #690017 is a reply to message #690010] Mon, 16 September 2024 11:19 Go to previous messageGo to next message
Nicha
Messages: 34
Registered: March 2020
Member
Nice Work @Michel Cadot

I'm most thankfull for your help.

My best regards
Re: Get most recent Value in one row only. (6 merged) [message #690018 is a reply to message #690012] Mon, 16 September 2024 11:24 Go to previous messageGo to next message
Nicha
Messages: 34
Registered: March 2020
Member
Hi @Solomon Yakobson

Thank you for your answer. Let me test onMy Database to analize it's performance.

I'll let you know.

I need to know what is the purpose of [match_recognize]. I'm a newbie os SQL.

Yhank you in advance.
Re: Get most recent Value in one row only. (6 merged) [message #690019 is a reply to message #690018] Mon, 16 September 2024 11:58 Go to previous message
Michel Cadot
Messages: 68728
Registered: March 2007
Location: Saint-Maur, France, https...
Senior Member
Account Moderator

MATCH_RECOGNIZE clause is an Oracle extension of SQL introduced in 12c like MODEL clause is another one introduced in 11gR2. They tell Oracle how to handle the rows.


Previous Topic: all the rows from two tables with conditions
Next Topic: ORA-29005: The certificate is invalid
Goto Forum:
  


Current Time: Sun Dec 22 00:15:27 CST 2024